chore: redesign docs
ad94bae7
43 file(s) · +2391 −40
| 1 | - | import clsx from "clsx"; |
|
| 2 | 1 | import type { ReactNode } from "react"; |
|
| 3 | 2 | ||
| 4 | 3 | export type ButtonProps = { |
|
| 7 | 6 | href?: string; |
|
| 8 | 7 | variant?: "accent"; |
|
| 9 | 8 | type?: "button" | "submit" | "reset" | "link"; |
|
| 10 | - | onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void; // Add this |
|
| 11 | - | onMouseOver?: (event: React.MouseEvent<HTMLButtonElement>) => void; // Add this too for hover |
|
| 12 | - | onMouseOut?: (event: React.MouseEvent<HTMLButtonElement>) => void; // And this |
|
| 9 | + | onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void; |
|
| 10 | + | }; |
|
| 11 | + | ||
| 12 | + | const baseStyle: React.CSSProperties = { |
|
| 13 | + | display: "inline-flex", |
|
| 14 | + | alignItems: "center", |
|
| 15 | + | justifyContent: "center", |
|
| 16 | + | padding: "0.4rem 0.75rem", |
|
| 17 | + | fontSize: "14px", |
|
| 18 | + | fontFamily: '"Commit Mono", monospace, sans-serif', |
|
| 19 | + | background: "#121113", |
|
| 20 | + | color: "#ffffff", |
|
| 21 | + | border: "1px solid white", |
|
| 22 | + | borderRadius: 0, |
|
| 23 | + | cursor: "pointer", |
|
| 24 | + | textDecoration: "none", |
|
| 25 | + | width: "fit-content", |
|
| 13 | 26 | }; |
|
| 14 | 27 | ||
| 15 | 28 | export function Button({ |
|
| 16 | 29 | children, |
|
| 17 | - | className, |
|
| 18 | 30 | href, |
|
| 19 | - | variant, |
|
| 20 | 31 | type = "button", |
|
| 21 | 32 | }: ButtonProps) { |
|
| 22 | - | const baseClassName = clsx( |
|
| 23 | - | className, |
|
| 24 | - | "inline-flex items-center justify-center px-4 py-2 text-sm font-medium rounded-md border border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-offset-2 hover:opacity-90", |
|
| 25 | - | variant === "accent" |
|
| 26 | - | ? "hover:opacity-90 focus:ring-orange-400 text-zinc-900 bg-[#ffb757]" |
|
| 27 | - | : "bg-zinc-900! text-zinc-200! hover:bg-zinc-800! focus:ring-gray-500!", |
|
| 28 | - | ); |
|
| 29 | - | ||
| 30 | 33 | if (type === "link") { |
|
| 31 | 34 | return ( |
|
| 32 | - | <a href={href} className={baseClassName}> |
|
| 35 | + | <a href={href} style={baseStyle}> |
|
| 33 | 36 | {children} |
|
| 34 | 37 | </a> |
|
| 35 | 38 | ); |
|
| 36 | 39 | } |
|
| 37 | 40 | ||
| 38 | 41 | return ( |
|
| 39 | - | <button |
|
| 40 | - | type={type} |
|
| 41 | - | className={baseClassName} |
|
| 42 | - | {...(type !== "submit" && href ? { href } : {})} |
|
| 43 | - | > |
|
| 42 | + | <button type={type} style={baseStyle}> |
|
| 44 | 43 | {children} |
|
| 45 | 44 | </button> |
|
| 46 | 45 | ); |
|
| 3 | 3 | export function Landing() { |
|
| 4 | 4 | return ( |
|
| 5 | 5 | <main |
|
| 6 | - | className="flex w-full sm:h-[85vh] min-h-[85vh] mt-6 mx-auto flex-col items-center justify-center gap-12 p-4 relative" |
|
| 7 | 6 | style={{ |
|
| 8 | - | backgroundImage: "url('/bg.png')", |
|
| 9 | - | backgroundPosition: "center", |
|
| 10 | - | backgroundRepeat: "no-repeat", |
|
| 11 | - | backgroundSize: "cover", |
|
| 12 | - | zIndex: 0, |
|
| 7 | + | display: "flex", |
|
| 8 | + | width: "100%", |
|
| 9 | + | minHeight: "85vh", |
|
| 10 | + | marginTop: "2rem", |
|
| 11 | + | flexDirection: "column", |
|
| 12 | + | alignItems: "center", |
|
| 13 | + | justifyContent: "center", |
|
| 14 | + | gap: "3rem", |
|
| 15 | + | padding: "1rem", |
|
| 16 | + | background: "#121113", |
|
| 13 | 17 | }} |
|
| 14 | 18 | > |
|
| 15 | 19 | <div |
|
| 16 | - | className="absolute inset-0 pointer-events-none" |
|
| 17 | 20 | style={{ |
|
| 18 | - | backgroundColor: "rgba(18, 17, 19, 0.7)", |
|
| 19 | - | zIndex: -1, |
|
| 21 | + | display: "flex", |
|
| 22 | + | flexDirection: "column", |
|
| 23 | + | alignItems: "center", |
|
| 24 | + | gap: "1.5rem", |
|
| 20 | 25 | }} |
|
| 21 | - | /> |
|
| 22 | - | ||
| 23 | - | <div className="flex flex-col items-center gap-12"> |
|
| 24 | - | <h1 className="text-center sm:text-6xl text-4xl font-black"> |
|
| 25 | - | Andromeda |
|
| 26 | + | > |
|
| 27 | + | <h1 |
|
| 28 | + | style={{ |
|
| 29 | + | textAlign: "center", |
|
| 30 | + | fontSize: "48px", |
|
| 31 | + | fontWeight: 700, |
|
| 32 | + | fontFamily: '"Commit Mono", monospace, sans-serif', |
|
| 33 | + | textTransform: "uppercase", |
|
| 34 | + | color: "#ffffff", |
|
| 35 | + | }} |
|
| 36 | + | > |
|
| 37 | + | Andromeda |
|
| 26 | 38 | </h1> |
|
| 27 | - | <h3 className="text-center sm:text-2xl text-lg font-semibold"> |
|
| 28 | - | Minimal, self-hosted personal software in Rust |
|
| 39 | + | <h3 |
|
| 40 | + | style={{ |
|
| 41 | + | textAlign: "center", |
|
| 42 | + | fontSize: "16px", |
|
| 43 | + | fontWeight: 400, |
|
| 44 | + | fontFamily: '"Commit Mono", monospace, sans-serif', |
|
| 45 | + | color: "#ffffff", |
|
| 46 | + | opacity: 0.7, |
|
| 47 | + | }} |
|
| 48 | + | > |
|
| 49 | + | Minimal, self-hosted personal software in Rust |
|
| 29 | 50 | </h3> |
|
| 30 | 51 | </div> |
|
| 31 | - | <div className="flex items-center gap-4"> |
|
| 32 | - | <Button type="link" variant="accent" href="/quickstart"> |
|
| 52 | + | <div style={{ display: "flex", alignItems: "center", gap: "1rem" }}> |
|
| 53 | + | <Button type="link" href="/quickstart"> |
|
| 33 | 54 | Get Started |
|
| 34 | 55 | </Button> |
|
| 35 | 56 | <Button type="link" href="https://github.com/stevedylandev/andromeda"> |
| 1 | + | <svg width="29" height="29" viewBox="0 0 29 29" fill="none" xmlns="http://www.w3.org/2000/svg"> |
|
| 2 | + | <path d="M29 2C29 0.895431 28.1046 4.68474e-07 27 4.68474e-07L9 4.68474e-07C7.89543 4.68474e-07 7 0.895431 7 2C7 3.10457 7.89543 4 9 4H25V20C25 21.1046 25.8954 22 27 22C28.1046 22 29 21.1046 29 20L29 2ZM3.41421 28.4142L28.4142 3.41421L25.5858 0.585787L0.585786 25.5858L3.41421 28.4142Z" fill="black"/> |
|
| 3 | + | </svg> |
| 1 | + | <svg |
|
| 2 | + | width="100%" |
|
| 3 | + | height="100%" |
|
| 4 | + | viewBox="0 0 69 39" |
|
| 5 | + | fill="none" |
|
| 6 | + | xmlns="http://www.w3.org/2000/svg" |
|
| 7 | + | > |
|
| 8 | + | <title>Chevron Down</title> |
|
| 9 | + | <path |
|
| 10 | + | d="M34.8677 38.8398C35.9419 38.8398 37.0161 38.4492 37.7485 37.6191L67.729 7.44339C68.4614 6.71089 68.9009 5.73439 68.9009 4.61129C68.9009 2.31639 67.1919 0.558594 64.897 0.558594C63.8227 0.558594 62.7485 1.04689 62.0161 1.73049L32.5727 31.2715H37.1138L7.67042 1.73049C6.93802 1.04689 5.96142 0.558594 4.83842 0.558594C2.54342 0.558594 0.785645 2.31639 0.785645 4.61129C0.785645 5.73439 1.22512 6.71089 1.95752 7.44339L31.9868 37.6191C32.768 38.4492 33.7446 38.8398 34.8677 38.8398Z" |
|
| 11 | + | fill="currentColor" |
|
| 12 | + | /> |
|
| 13 | + | </svg> |
| 1 | + | <svg |
|
| 2 | + | width="100%" |
|
| 3 | + | height="100%" |
|
| 4 | + | viewBox="0 0 69 40" |
|
| 5 | + | fill="none" |
|
| 6 | + | xmlns="http://www.w3.org/2000/svg" |
|
| 7 | + | > |
|
| 8 | + | <title>Chevron Up</title> |
|
| 9 | + | <path |
|
| 10 | + | d="M1.95752 32.2441C1.22512 32.9277 0.785645 33.9531 0.785645 35.0762C0.785645 37.3711 2.54342 39.1289 4.83842 39.1289C5.96142 39.1289 6.98682 38.6895 7.67042 37.957L37.1138 8.36716H32.5727L62.0161 37.957C62.6997 38.6895 63.8227 39.1289 64.897 39.1289C67.1919 39.1289 68.9009 37.3711 68.9009 35.0762C68.9009 33.9531 68.4614 32.9277 67.729 32.2441L37.7485 2.06836C37.0161 1.23826 35.9419 0.847656 34.8677 0.847656C33.7446 0.847656 32.7192 1.23826 31.9868 2.06836L1.95752 32.2441Z" |
|
| 11 | + | fill="currentColor" |
|
| 12 | + | /> |
|
| 13 | + | </svg> |
| 1 | + | <svg width="83" height="83" viewBox="0 0 83 83" fill="none" xmlns="http://www.w3.org/2000/svg"> |
|
| 2 | + | <path d="M43.6479 25.4375L37.8862 31.2969C42.476 31.9316 45.4546 33.3965 47.7006 35.6426C54.2436 42.1855 54.2436 51.3652 47.7983 57.8105L35.2983 70.3105C28.8042 76.8047 19.6245 76.8047 13.0815 70.3105C6.48974 63.7188 6.53854 54.5391 13.0327 48.0938L19.6245 41.502C18.4038 38.6699 18.1108 35.4473 18.4526 32.7129L7.75924 43.4062C-1.66455 52.7812 -1.71338 66.1113 7.80814 75.584C17.2807 85.1055 30.562 85.0566 39.9858 75.6328L53.0717 62.498C62.4467 53.123 62.4956 39.8418 53.0229 30.3203C50.8745 28.1719 48.0913 26.5605 43.6479 25.4375ZM40.0346 57.4199L45.7475 51.6094C41.1577 50.9746 38.1792 49.5098 35.9819 47.2637C29.4389 40.7207 29.4389 31.541 35.8842 25.0957L48.3842 12.5957C54.8784 6.1016 64.0581 6.0527 70.601 12.5957C77.144 19.1875 77.0952 28.3672 70.6499 34.8125L64.0581 41.4043C65.2788 44.2363 65.5717 47.459 65.2299 50.1934L75.9233 39.5C85.3471 30.0762 85.396 16.7949 75.8745 7.3223C66.4018 -2.1992 53.0717 -2.15041 43.6967 7.27339L30.6108 20.4082C21.2358 29.7832 21.1381 43.0645 30.6596 52.5859C32.8081 54.7344 35.5913 56.3457 40.0346 57.4199Z" fill="currentColor"/> |
|
| 3 | + | </svg> |
| 1 | + | {"documentCount":105,"nextId":105,"documentIds":{"0":"docs/pages/quickstart.mdx#quickstart","1":"docs/pages/quickstart.mdx#prerequisites","2":"docs/pages/quickstart.mdx#clone-the-workspace","3":"docs/pages/quickstart.mdx#build-all-apps","4":"docs/pages/quickstart.mdx#run-a-specific-app","5":"docs/pages/quickstart.mdx#environment-variables","6":"docs/pages/quickstart.mdx#deployment","7":"docs/pages/what-is-andromeda.mdx#what-is-andromeda","8":"docs/pages/what-is-andromeda.mdx#philosophy","9":"docs/pages/what-is-andromeda.mdx#apps","10":"docs/pages/what-is-andromeda.mdx#shared-crates","11":"docs/pages/what-is-andromeda.mdx#license","12":"docs/pages/diy/skills.mdx#skills","13":"docs/pages/diy/skills.mdx#what-is-rust-crud","14":"docs/pages/diy/skills.mdx#using-the-skill","15":"docs/pages/diy/skills.mdx#building-your-own-app","16":"docs/pages/diy/skills.mdx#1-create-the-app-directory","17":"docs/pages/diy/skills.mdx#2-add-to-workspace","18":"docs/pages/diy/skills.mdx#3-set-up-cargotoml","19":"docs/pages/diy/skills.mdx#4-follow-the-pattern","20":"docs/pages/diy/skills.mdx#5-build-and-run","21":"docs/pages/diy/stack.mdx#stack","22":"docs/pages/diy/stack.mdx#core-dependencies","23":"docs/pages/diy/stack.mdx#axum","24":"docs/pages/diy/stack.mdx#sqlite-rusqlite","25":"docs/pages/diy/stack.mdx#askama","26":"docs/pages/diy/stack.mdx#rust-embed","27":"docs/pages/diy/stack.mdx#tokio","28":"docs/pages/diy/stack.mdx#shared-crate-andromeda-auth","29":"docs/pages/diy/stack.mdx#app-pattern","30":"docs/pages/apps/feeds.mdx#feeds","31":"docs/pages/apps/feeds.mdx#overview","32":"docs/pages/apps/feeds.mdx#quickstart","33":"docs/pages/apps/feeds.mdx#environment-variables","34":"docs/pages/apps/feeds.mdx#usage","35":"docs/pages/apps/feeds.mdx#url-query-param","36":"docs/pages/apps/feeds.mdx#opml-file","37":"docs/pages/apps/feeds.mdx#freshrss-api","38":"docs/pages/apps/feeds.mdx#admin-panel","39":"docs/pages/apps/feeds.mdx#feeds-api","40":"docs/pages/apps/feeds.mdx#structure","41":"docs/pages/apps/feeds.mdx#deployment","42":"docs/pages/apps/feeds.mdx#railway","43":"docs/pages/apps/feeds.mdx#docker","44":"docs/pages/apps/feeds.mdx#binary","45":"docs/pages/apps/jotts.mdx#jotts","46":"docs/pages/apps/jotts.mdx#overview","47":"docs/pages/apps/jotts.mdx#quickstart","48":"docs/pages/apps/jotts.mdx#environment-variables","49":"docs/pages/apps/jotts.mdx#structure","50":"docs/pages/apps/jotts.mdx#deployment","51":"docs/pages/apps/jotts.mdx#railway","52":"docs/pages/apps/jotts.mdx#docker","53":"docs/pages/apps/jotts.mdx#binary","54":"docs/pages/apps/og.mdx#og","55":"docs/pages/apps/og.mdx#overview","56":"docs/pages/apps/og.mdx#quickstart","57":"docs/pages/apps/og.mdx#environment-variables","58":"docs/pages/apps/og.mdx#structure","59":"docs/pages/apps/og.mdx#deployment","60":"docs/pages/apps/og.mdx#railway","61":"docs/pages/apps/og.mdx#docker","62":"docs/pages/apps/og.mdx#binary","63":"docs/pages/apps/parcels.mdx#parcels","64":"docs/pages/apps/parcels.mdx#overview","65":"docs/pages/apps/parcels.mdx#quickstart","66":"docs/pages/apps/parcels.mdx#environment-variables","67":"docs/pages/apps/parcels.mdx#structure","68":"docs/pages/apps/parcels.mdx#deployment","69":"docs/pages/apps/parcels.mdx#railway","70":"docs/pages/apps/parcels.mdx#docker","71":"docs/pages/apps/parcels.mdx#binary","72":"docs/pages/apps/shrink.mdx#shrink","73":"docs/pages/apps/shrink.mdx#overview","74":"docs/pages/apps/shrink.mdx#quickstart","75":"docs/pages/apps/shrink.mdx#environment-variables","76":"docs/pages/apps/shrink.mdx#structure","77":"docs/pages/apps/shrink.mdx#deployment","78":"docs/pages/apps/shrink.mdx#railway","79":"docs/pages/apps/shrink.mdx#docker","80":"docs/pages/apps/shrink.mdx#binary","81":"docs/pages/apps/sipp.mdx#sipp","82":"docs/pages/apps/sipp.mdx#overview","83":"docs/pages/apps/sipp.mdx#quickstart","84":"docs/pages/apps/sipp.mdx#install","85":"docs/pages/apps/sipp.mdx#homebrew","86":"docs/pages/apps/sipp.mdx#cargo","87":"docs/pages/apps/sipp.mdx#releases","88":"docs/pages/apps/sipp.mdx#cli","89":"docs/pages/apps/sipp.mdx#commands","90":"docs/pages/apps/sipp.mdx#arguments","91":"docs/pages/apps/sipp.mdx#options","92":"docs/pages/apps/sipp.mdx#server","93":"docs/pages/apps/sipp.mdx#environment-variables","94":"docs/pages/apps/sipp.mdx#api-endpoints","95":"docs/pages/apps/sipp.mdx#raw-output-for-cli-tools","96":"docs/pages/apps/sipp.mdx#tui","97":"docs/pages/apps/sipp.mdx#local-access","98":"docs/pages/apps/sipp.mdx#remote-access","99":"docs/pages/apps/sipp.mdx#keybindings","100":"docs/pages/apps/sipp.mdx#structure","101":"docs/pages/apps/sipp.mdx#deployment","102":"docs/pages/apps/sipp.mdx#railway","103":"docs/pages/apps/sipp.mdx#docker","104":"docs/pages/apps/sipp.mdx#binary"},"fieldIds":{"title":0,"titles":1,"text":2},"fieldLength":{"0":[1,1,11],"1":[1,1,8],"2":[3,1,9],"3":[3,1,4],"4":[4,1,43],"5":[2,1,22],"6":[1,1,40],"7":[3,1,25],"8":[1,3,63],"9":[1,3,21],"10":[2,3,27],"11":[1,3,2],"12":[1,1,29],"13":[5,1,44],"14":[3,1,33],"15":[4,1,15],"16":[5,5,9],"17":[4,5,16],"18":[5,5,34],"19":[4,5,28],"20":[4,5,6],"21":[1,1,22],"22":[2,1,1],"23":[1,3,39],"24":[3,3,23],"25":[1,3,33],"26":[2,3,31],"27":[1,3,10],"28":[4,1,31],"29":[2,1,54],"30":[1,1,4],"31":[1,1,75],"32":[1,1,19],"33":[2,2,23],"34":[1,1,11],"35":[3,2,32],"36":[2,2,23],"37":[2,2,25],"38":[2,2,34],"39":[2,2,15],"40":[1,1,51],"41":[1,1,1],"42":[1,2,1],"43":[1,2,15],"44":[1,2,28],"45":[1,1,5],"46":[1,1,41],"47":[1,1,21],"48":[2,2,21],"49":[1,1,70],"50":[1,1,1],"51":[1,2,1],"52":[1,2,29],"53":[1,2,28],"54":[1,1,13],"55":[1,1,41],"56":[1,1,13],"57":[2,2,3],"58":[1,1,43],"59":[1,1,1],"60":[1,2,1],"61":[1,2,8],"62":[1,2,24],"63":[1,1,25],"64":[1,1,38],"65":[1,1,39],"66":[2,2,24],"67":[1,1,62],"68":[1,1,1],"69":[1,2,1],"70":[1,2,29],"71":[1,2,26],"72":[1,1,6],"73":[1,1,42],"74":[1,1,13],"75":[2,2,7],"76":[1,1,30],"77":[1,1,1],"78":[1,2,1],"79":[1,2,15],"80":[1,2,20],"81":[1,1,4],"82":[1,1,64],"83":[1,1,24],"84":[1,2,7],"85":[1,3,7],"86":[1,3,5],"87":[1,3,10],"88":[1,1,5],"89":[1,2,15],"90":[1,2,10],"91":[1,2,18],"92":[1,1,19],"93":[2,2,46],"94":[2,2,30],"95":[5,2,30],"96":[1,1,41],"97":[2,2,23],"98":[2,2,27],"99":[1,2,27],"100":[1,1,54],"101":[1,1,1],"102":[1,2,1],"103":[1,2,10],"104":[1,2,27]},"averageFieldLength":[1.6095238095238096,1.7809523809523808,22.276190476190475],"storedFields":{"0":{"href":"/quickstart#quickstart","html":"</header>\n<p>Get up and running with any Andromeda app in minutes.</p>\n","isPage":true,"text":"\nGet up and running with any Andromeda app in minutes.\n","title":"Quickstart","titles":[]},"1":{"href":"/quickstart#prerequisites","html":"\n<p>Make sure <a href=\"https://www.rust-lang.org/tools/install\">Rust</a> is installed:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">rustc</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> --version</span></span></code></pre>\n","isPage":false,"text":"\nMake sure Rust is installed:\nrustc --version\n","title":"Prerequisites","titles":["Quickstart"]},"2":{"href":"/quickstart#clone-the-workspace","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">git</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> clone</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> https://github.com/stevedylandev/andromeda.git</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\">cd</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> andromeda</span></span></code></pre>\n","isPage":false,"text":"\ngit clone https://github.com/stevedylandev/andromeda.git\ncd andromeda\n","title":"Clone the Workspace","titles":["Quickstart"]},"3":{"href":"/quickstart#build-all-apps","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> build</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> --release</span></span></code></pre>\n","isPage":false,"text":"\ncargo build --release\n","title":"Build All Apps","titles":["Quickstart"]},"4":{"href":"/quickstart#run-a-specific-app","html":"\n<p>Each app is a workspace member. Run any of them with <code>cargo run -p</code>:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> run</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> sipp</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> --</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> server</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> --port</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> 3000</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> run</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> feeds</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> run</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> parcels</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> run</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> jotts</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> run</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> og</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> run</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> shrink</span></span></code></pre>\n<p>Most apps start on <code>http://localhost:3000</code> by default. Check each app's page for specific environment variables and configuration.</p>\n","isPage":false,"text":"\nEach app is a workspace member. Run any of them with cargo run -p:\ncargo run -p sipp -- server --port 3000\ncargo run -p feeds\ncargo run -p parcels\ncargo run -p jotts\ncargo run -p og\ncargo run -p shrink\nMost apps start on http://localhost:3000 by default. Check each app's page for specific environment variables and configuration.\n","title":"Run a Specific App","titles":["Quickstart"]},"5":{"href":"/quickstart#environment-variables","html":"\n<p>Most apps use a <code>.env</code> file for configuration. Copy the example file and fill in your values:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cp</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> apps/</span><span style=\"color:#D73A49;--shiki-dark:#F47067\"><</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">app-nam</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">e</span><span style=\"color:#D73A49;--shiki-dark:#F47067\">></span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">/.env.example</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> .env</span></span></code></pre>\n","isPage":false,"text":"\nMost apps use a .env file for configuration. Copy the example file and fill in your values:\ncp apps/<app-name>/.env.example .env\n","title":"Environment Variables","titles":["Quickstart"]},"6":{"href":"/quickstart#deployment","html":"\n<p>Every app compiles to a single binary with embedded assets, making deployment straightforward. Each app supports:</p>\n<ul>\n<li><strong>Railway</strong> - one-click deploy buttons on each app's page</li>\n<li><strong>Docker</strong> - <code>docker compose up -d</code></li>\n<li><strong>Binary</strong> - copy the binary to your server and run it directly</li>\n</ul>","isPage":false,"text":"\nEvery app compiles to a single binary with embedded assets, making deployment straightforward. Each app supports:\n\nRailway - one-click deploy buttons on each app's page\nDocker - docker compose up -d\nBinary - copy the binary to your server and run it directly\n","title":"Deployment","titles":["Quickstart"]},"7":{"href":"/what-is-andromeda#what-is-andromeda","html":"</header>\n<p>Andromeda is a Rust workspace of minimal, self-hosted web apps. Each app compiles to a single binary powered by <a href=\"https://github.com/tokio-rs/axum\">Axum</a>, <a href=\"https://github.com/rusqlite/rusqlite\">SQLite</a>, and <a href=\"https://github.com/djc/askama\">Askama</a> templates.</p>\n","isPage":true,"text":"\nAndromeda is a Rust workspace of minimal, self-hosted web apps. Each app compiles to a single binary powered by Axum, SQLite, and Askama templates.\n","title":"What is Andromeda","titles":[]},"8":{"href":"/what-is-andromeda#philosophy","html":"\n<p>Every app in Andromeda follows the same principles:</p>\n<ul>\n<li><strong>Single binary</strong> - Each app compiles to one small binary (~7MB) with all assets embedded at compile time</li>\n<li><strong>Minimal resource usage</strong> - Apps average around ~10MB of RAM</li>\n<li><strong>Self-hosted</strong> - You own your data and run it on your own infrastructure</li>\n<li><strong>Simple deployment</strong> - One binary, one optional <code>.env</code> file, no external dependencies</li>\n<li><strong>Consistent stack</strong> - All apps share the same Rust stack so patterns are transferable</li>\n</ul>\n","isPage":false,"text":"\nEvery app in Andromeda follows the same principles:\n\nSingle binary - Each app compiles to one small binary (~7MB) with all assets embedded at compile time\nMinimal resource usage - Apps average around ~10MB of RAM\nSelf-hosted - You own your data and run it on your own infrastructure\nSimple deployment - One binary, one optional .env file, no external dependencies\nConsistent stack - All apps share the same Rust stack so patterns are transferable\n\n","title":"Philosophy","titles":["What is Andromeda"]},"9":{"href":"/what-is-andromeda#apps","html":"\n<table><thead><tr><th>App</th><th>Description</th></tr></thead><tbody><tr><td><a href=\"/apps/sipp\">Sipp</a></td><td>Code sharing with web UI and TUI</td></tr><tr><td><a href=\"/apps/feeds\">Feeds</a></td><td>RSS reader with FreshRSS and OPML support</td></tr><tr><td><a href=\"/apps/parcels\">Parcels</a></td><td>Package tracking (USPS)</td></tr><tr><td><a href=\"/apps/jotts\">Jotts</a></td><td>Markdown notes</td></tr><tr><td><a href=\"/apps/og\">OG</a></td><td>Open Graph tag inspector</td></tr><tr><td><a href=\"/apps/shrink\">Shrink</a></td><td>Image compression and resizing</td></tr></tbody></table>\n","isPage":false,"text":"\nAppDescriptionSippCode sharing with web UI and TUIFeedsRSS reader with FreshRSS and OPML supportParcelsPackage tracking (USPS)JottsMarkdown notesOGOpen Graph tag inspectorShrinkImage compression and resizing\n","title":"Apps","titles":["What is Andromeda"]},"10":{"href":"/what-is-andromeda#shared-crates","html":"\n<table><thead><tr><th>Crate</th><th>Description</th></tr></thead><tbody><tr><td><code>andromeda-auth</code></td><td>Session-based password authentication</td></tr></tbody></table>\n<p>The <code>andromeda-auth</code> crate provides a shared authentication layer used across apps that require login, including session cookies and constant-time password verification.</p>\n","isPage":false,"text":"\nCrateDescriptionandromeda-authSession-based password authentication\nThe andromeda-auth crate provides a shared authentication layer used across apps that require login, including session cookies and constant-time password verification.\n","title":"Shared Crates","titles":["What is Andromeda"]},"11":{"href":"/what-is-andromeda#license","html":"\n<p><a href=\"https://github.com/stevedylandev/andromeda/blob/main/LICENSE\">MIT</a></p>","isPage":false,"text":"\nMIT","title":"License","titles":["What is Andromeda"]},"12":{"href":"/diy/skills#skills","html":"</header>\n<p>Andromeda apps are scaffolded using <a href=\"https://claude.ai/code\">Claude Code</a> with a custom skill called <code>rust-crud</code>. This page explains how to use it to build your own apps in the same style.</p>\n","isPage":true,"text":"\nAndromeda apps are scaffolded using Claude Code with a custom skill called rust-crud. This page explains how to use it to build your own apps in the same style.\n","title":"Skills","titles":[]},"13":{"href":"/diy/skills#what-is-rust-crud","html":"\n<p><code>rust-crud</code> is a Claude Code skill that scaffolds a complete Rust CRUD web application matching the Andromeda stack:</p>\n<ul>\n<li>Axum web server with routing</li>\n<li>SQLite database with rusqlite</li>\n<li>Askama HTML templates</li>\n<li>API key authentication</li>\n<li>Embedded static assets via rust-embed</li>\n<li>Dockerfile and docker-compose.yml for deployment</li>\n</ul>\n","isPage":false,"text":"\nrust-crud is a Claude Code skill that scaffolds a complete Rust CRUD web application matching the Andromeda stack:\n\nAxum web server with routing\nSQLite database with rusqlite\nAskama HTML templates\nAPI key authentication\nEmbedded static assets via rust-embed\nDockerfile and docker-compose.yml for deployment\n\n","title":"What is rust-crud?","titles":["Skills"]},"14":{"href":"/diy/skills#using-the-skill","html":"\n<p>In Claude Code, invoke the skill when you want to create a new app:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">/rust-crud</span></span></code></pre>\n<p>Describe what you want to build and the skill will generate a complete, working app that follows the same patterns as every other Andromeda app.</p>\n","isPage":false,"text":"\nIn Claude Code, invoke the skill when you want to create a new app:\n/rust-crud\nDescribe what you want to build and the skill will generate a complete, working app that follows the same patterns as every other Andromeda app.\n","title":"Using the Skill","titles":["Skills"]},"15":{"href":"/diy/skills#building-your-own-app","html":"\n<p>If you want to add a new app to the workspace manually, follow these steps:</p>\n","isPage":false,"text":"\nIf you want to add a new app to the workspace manually, follow these steps:\n","title":"Building Your Own App","titles":["Skills"]},"16":{"href":"/diy/skills#1-create-the-app-directory","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">mkdir</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> apps/my-app/src</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">mkdir</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> apps/my-app/templates</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">mkdir</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> apps/my-app/static</span></span></code></pre>\n","isPage":false,"text":"\nmkdir -p apps/my-app/src\nmkdir -p apps/my-app/templates\nmkdir -p apps/my-app/static\n","title":"1. Create the app directory","titles":["Skills","Building Your Own App"]},"17":{"href":"/diy/skills#2-add-to-workspace","html":"\n<p>Add your app to the root <code>Cargo.toml</code> workspace members:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">[</span><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">workspace</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">]</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">members = [</span></span>\n<span class=\"line\"><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> "apps/my-app"</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">,</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#768390\"> # ...existing apps</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">]</span></span></code></pre>\n","isPage":false,"text":"\nAdd your app to the root Cargo.toml workspace members:\n[workspace]\nmembers = [\n "apps/my-app",\n # ...existing apps\n]\n","title":"2. Add to workspace","titles":["Skills","Building Your Own App"]},"18":{"href":"/diy/skills#3-set-up-cargotoml","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">[</span><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">package</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">]</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">name = </span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"my-app"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">version = </span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"0.1.0"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">edition = </span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"2021"</span></span>\n<span class=\"line\" data-empty-line=\"true\"> </span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">[</span><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">dependencies</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">]</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">axum = </span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"0.8"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">tokio = { version = </span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"1"</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">, features = [</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"full"</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">] }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">rusqlite = { version = </span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"0.32"</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">, features = [</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"bundled"</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">] }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">askama = </span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"0.12"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">askama_axum = </span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"0.4"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">rust-embed = </span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"8"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">tower-http = { version = </span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"0.6"</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">, features = [</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"cors"</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">] }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">serde = { version = </span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"1"</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">, features = [</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"derive"</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">] }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">dotenvy = </span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"0.15"</span></span></code></pre>\n","isPage":false,"text":"\n[package]\nname = "my-app"\nversion = "0.1.0"\nedition = "2021"\n \n[dependencies]\naxum = "0.8"\ntokio = { version = "1", features = ["full"] }\nrusqlite = { version = "0.32", features = ["bundled"] }\naskama = "0.12"\naskama_axum = "0.4"\nrust-embed = "8"\ntower-http = { version = "0.6", features = ["cors"] }\nserde = { version = "1", features = ["derive"] }\ndotenvy = "0.15"\n","title":"3. Set up Cargo.toml","titles":["Skills","Building Your Own App"]},"19":{"href":"/diy/skills#4-follow-the-pattern","html":"\n<p>Use the <a href=\"/diy/stack\">Stack</a> page as a reference for how to structure your <code>main.rs</code>, <code>server.rs</code>, and <code>db.rs</code> files. Look at any existing app in <code>apps/</code> for a working example.</p>\n","isPage":false,"text":"\nUse the Stack page as a reference for how to structure your main.rs, server.rs, and db.rs files. Look at any existing app in apps/ for a working example.\n","title":"4. Follow the pattern","titles":["Skills","Building Your Own App"]},"20":{"href":"/diy/skills#5-build-and-run","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> run</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> my-app</span></span></code></pre>","isPage":false,"text":"\ncargo run -p my-app","title":"5. Build and run","titles":["Skills","Building Your Own App"]},"21":{"href":"/diy/stack#stack","html":"</header>\n<p>Every app in Andromeda is built on the same Rust stack. This page covers the core dependencies and how they fit together.</p>\n","isPage":true,"text":"\nEvery app in Andromeda is built on the same Rust stack. This page covers the core dependencies and how they fit together.\n","title":"Stack","titles":[]},"22":{"href":"/diy/stack#core-dependencies","html":"\n","isPage":false,"text":"\n","title":"Core Dependencies","titles":["Stack"]},"23":{"href":"/diy/stack#axum","html":"\n<p><a href=\"https://github.com/tokio-rs/axum\">Axum</a> is the web framework powering every app. It provides routing, request extraction, middleware, and response handling. All apps follow a similar pattern:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F47067\">let</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\"> app </span><span style=\"color:#D73A49;--shiki-dark:#F47067\">=</span><span style=\"color:#6F42C1;--shiki-dark:#F69D50\"> Router</span><span style=\"color:#D73A49;--shiki-dark:#F47067\">::</span><span style=\"color:#6F42C1;--shiki-dark:#DCBDFB\">new</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">()</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F47067\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#DCBDFB\">route</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">(</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"/"</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">, </span><span style=\"color:#6F42C1;--shiki-dark:#DCBDFB\">get</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">(index))</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F47067\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#DCBDFB\">route</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">(</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">"/api/items"</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">, </span><span style=\"color:#6F42C1;--shiki-dark:#DCBDFB\">post</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">(create_item))</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F47067\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#DCBDFB\">with_state</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">(app_state);</span></span></code></pre>\n","isPage":false,"text":"\nAxum is the web framework powering every app. It provides routing, request extraction, middleware, and response handling. All apps follow a similar pattern:\nlet app = Router::new()\n .route("/", get(index))\n .route("/api/items", post(create_item))\n .with_state(app_state);\n","title":"Axum","titles":["Stack","Core Dependencies"]},"24":{"href":"/diy/stack#sqlite-rusqlite","html":"\n<p><a href=\"https://github.com/rusqlite/rusqlite\">rusqlite</a> provides the storage layer. Each app creates its own SQLite database file, keeping data local and portable. No external database server needed.</p>\n","isPage":false,"text":"\nrusqlite provides the storage layer. Each app creates its own SQLite database file, keeping data local and portable. No external database server needed.\n","title":"SQLite (rusqlite)","titles":["Stack","Core Dependencies"]},"25":{"href":"/diy/stack#askama","html":"\n<p><a href=\"https://github.com/djc/askama\">Askama</a> handles HTML templating with compile-time checked templates. Templates live in a <code>templates/</code> directory and are type-safe Rust structs:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">#[derive(</span><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">Template</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">)]</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">#[template(path </span><span style=\"color:#D73A49;--shiki-dark:#F47067\">=</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> "index.html"</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">)]</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F47067\">struct</span><span style=\"color:#6F42C1;--shiki-dark:#F69D50\"> IndexTemplate</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\"> items</span><span style=\"color:#D73A49;--shiki-dark:#F47067\">:</span><span style=\"color:#6F42C1;--shiki-dark:#F69D50\"> Vec</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">,</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">}</span></span></code></pre>\n","isPage":false,"text":"\nAskama handles HTML templating with compile-time checked templates. Templates live in a templates/ directory and are type-safe Rust structs:\n#[derive(Template)]\n#[template(path = "index.html")]\nstruct IndexTemplate {\n items: Vec,\n}\n","title":"Askama","titles":["Stack","Core Dependencies"]},"26":{"href":"/diy/stack#rust-embed","html":"\n<p><a href=\"https://github.com/pyrossh/rust-embed\">rust-embed</a> embeds static assets (CSS, fonts, images) directly into the binary at compile time. This is what makes each app a single, self-contained binary with no external file dependencies.</p>\n","isPage":false,"text":"\nrust-embed embeds static assets (CSS, fonts, images) directly into the binary at compile time. This is what makes each app a single, self-contained binary with no external file dependencies.\n","title":"rust-embed","titles":["Stack","Core Dependencies"]},"27":{"href":"/diy/stack#tokio","html":"\n<p><a href=\"https://tokio.rs\">Tokio</a> provides the async runtime that Axum runs on.</p>\n","isPage":false,"text":"\nTokio provides the async runtime that Axum runs on.\n","title":"Tokio","titles":["Stack","Core Dependencies"]},"28":{"href":"/diy/stack#shared-crate-andromeda-auth","html":"\n<p>The <code>andromeda-auth</code> crate provides session-based password authentication used across apps that require login. It handles:</p>\n<ul>\n<li>Constant-time password verification</li>\n<li>Session cookie management</li>\n<li>Secure cookie configuration via <code>COOKIE_SECURE</code> env var</li>\n</ul>\n","isPage":false,"text":"\nThe andromeda-auth crate provides session-based password authentication used across apps that require login. It handles:\n\nConstant-time password verification\nSession cookie management\nSecure cookie configuration via COOKIE_SECURE env var\n\n","title":"Shared Crate: andromeda-auth","titles":["Stack"]},"29":{"href":"/diy/stack#app-pattern","html":"\n<p>Every app follows a consistent structure:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">app/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── src/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── main.rs # Entry point, env vars, starts server</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── server.rs # Axum routes and handlers</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── db.rs # SQLite database layer</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ └── auth.rs # Authentication (if needed)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── templates/ # Askama HTML templates</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── static/ # Fonts, favicons, styles</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── Dockerfile</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">└── docker-compose.yml</span></span></code></pre>\n<p>This consistency means once you understand one app, you can navigate any of them.</p>","isPage":false,"text":"\nEvery app follows a consistent structure:\napp/\n├── src/\n│ ├── main.rs # Entry point, env vars, starts server\n│ ├── server.rs # Axum routes and handlers\n│ ├── db.rs # SQLite database layer\n│ └── auth.rs # Authentication (if needed)\n├── templates/ # Askama HTML templates\n├── static/ # Fonts, favicons, styles\n├── Dockerfile\n└── docker-compose.yml\nThis consistency means once you understand one app, you can navigate any of them.","title":"App Pattern","titles":["Stack"]},"30":{"href":"/apps/feeds#feeds","html":"</header>\n<p>Minimal RSS Feeds</p>\n","isPage":true,"text":"\nMinimal RSS Feeds\n","title":"Feeds","titles":[]},"31":{"href":"/apps/feeds#overview","html":"\n<p>Feeds is a minimal RSS reader that mimics the original experience of RSS. It's just a list of posts. No categories, no marking a post read or unread, and there is no in-app reading. With this approach you have to read the post on the author's personal website and experience it in its original context.</p>\n<ul>\n<li>Single Rust binary with embedded assets</li>\n<li>Multiple feed sources: URL params, OPML file, or FreshRSS API</li>\n<li>Password-protected admin panel for managing subscriptions</li>\n<li>Feeds API with JSON and OPML export</li>\n<li>Dark themed UI with Commit Mono font</li>\n</ul>\n","isPage":false,"text":"\nFeeds is a minimal RSS reader that mimics the original experience of RSS. It's just a list of posts. No categories, no marking a post read or unread, and there is no in-app reading. With this approach you have to read the post on the author's personal website and experience it in its original context.\n\nSingle Rust binary with embedded assets\nMultiple feed sources: URL params, OPML file, or FreshRSS API\nPassword-protected admin panel for managing subscriptions\nFeeds API with JSON and OPML export\nDark themed UI with Commit Mono font\n\n","title":"Overview","titles":["Feeds"]},"32":{"href":"/apps/feeds#quickstart","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">git</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> clone</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> https://github.com/stevedylandev/andromeda.git</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\">cd</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> andromeda</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> run</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> feeds</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#768390\"># Server running on http://localhost:3000</span></span></code></pre>\n","isPage":false,"text":"\ngit clone https://github.com/stevedylandev/andromeda.git\ncd andromeda\ncargo run -p feeds\n# Server running on http://localhost:3000\n","title":"Quickstart","titles":["Feeds"]},"33":{"href":"/apps/feeds#environment-variables","html":"\n<table><thead><tr><th>Variable</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>FRESHRSS_URL</code></td><td>URL of your FreshRSS instance</td><td>--</td></tr><tr><td><code>FRESHRSS_USERNAME</code></td><td>FreshRSS username</td><td>--</td></tr><tr><td><code>FRESHRSS_PASSWORD</code></td><td>FreshRSS password</td><td>--</td></tr><tr><td><code>ADMIN_PASSWORD</code></td><td>Password for the admin panel</td><td>--</td></tr><tr><td><code>COOKIE_SECURE</code></td><td>Enable HTTPS-only cookies</td><td><code>false</code></td></tr></tbody></table>\n","isPage":false,"text":"\nVariableDescriptionDefaultFRESHRSS_URLURL of your FreshRSS instance--FRESHRSS_USERNAMEFreshRSS username--FRESHRSS_PASSWORDFreshRSS password--ADMIN_PASSWORDPassword for the admin panel--COOKIE_SECUREEnable HTTPS-only cookiesfalse\n","title":"Environment Variables","titles":["Feeds","Quickstart"]},"34":{"href":"/apps/feeds#usage","html":"\n<p>There are several built-in ways to source RSS feeds.</p>\n","isPage":false,"text":"\nThere are several built-in ways to source RSS feeds.\n","title":"Usage","titles":["Feeds"]},"35":{"href":"/apps/feeds#url-query-param","html":"\n<p>Once you have the app running you can add the following to the URL to source an RSS feed:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">?url=https://bearblog.dev/discover/feed/</span></span></code></pre>\n<p>You can also add multiple URLs by using commas to separate them:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">?urls=https://bearblog.dev/discover/feed/,https://bearblog.stevedylan.dev/feed/</span></span></code></pre>\n","isPage":false,"text":"\nOnce you have the app running you can add the following to the URL to source an RSS feed:\n?url=https://bearblog.dev/discover/feed/\nYou can also add multiple URLs by using commas to separate them:\n?urls=https://bearblog.dev/discover/feed/,https://bearblog.stevedylan.dev/feed/\n","title":"URL Query Param","titles":["Feeds","Usage"]},"36":{"href":"/apps/feeds#opml-file","html":"\n<p>If you save a <code>feeds.opml</code> file in the root of the project the app will automatically source it and fetch the posts for the feeds inside.</p>\n","isPage":false,"text":"\nIf you save a feeds.opml file in the root of the project the app will automatically source it and fetch the posts for the feeds inside.\n","title":"OPML File","titles":["Feeds","Usage"]},"37":{"href":"/apps/feeds#freshrss-api","html":"\n<p>If neither of the above are provided the app will default to using a FreshRSS API instance. Set the following environment variables:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">FRESHRSS_URL=</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">FRESHRSS_USERNAME=</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">FRESHRSS_PASSWORD=</span></span></code></pre>\n","isPage":false,"text":"\nIf neither of the above are provided the app will default to using a FreshRSS API instance. Set the following environment variables:\nFRESHRSS_URL=\nFRESHRSS_USERNAME=\nFRESHRSS_PASSWORD=\n","title":"FreshRSS API","titles":["Feeds","Usage"]},"38":{"href":"/apps/feeds#admin-panel","html":"\n<p>Feeds includes a password-protected admin panel at <code>/admin</code> for managing your FreshRSS subscriptions. Set the <code>ADMIN_PASSWORD</code> environment variable to enable it. From the admin panel you can view your current subscriptions and add new feeds directly to your FreshRSS instance.</p>\n","isPage":false,"text":"\nFeeds includes a password-protected admin panel at /admin for managing your FreshRSS subscriptions. Set the ADMIN_PASSWORD environment variable to enable it. From the admin panel you can view your current subscriptions and add new feeds directly to your FreshRSS instance.\n","title":"Admin Panel","titles":["Feeds","Usage"]},"39":{"href":"/apps/feeds#feeds-api","html":"\n<p>The <code>/feeds</code> endpoint exports your FreshRSS subscriptions in JSON or OPML format:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">/feeds?format=json</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">/feeds?format=opml</span></span></code></pre>\n","isPage":false,"text":"\nThe /feeds endpoint exports your FreshRSS subscriptions in JSON or OPML format:\n/feeds?format=json\n/feeds?format=opml\n","title":"Feeds API","titles":["Feeds","Usage"]},"40":{"href":"/apps/feeds#structure","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">feeds/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── src/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── main.rs # Axum server with routing, templates, and static asset serving</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── feeds.rs # Feed fetching, OPML parsing, and FreshRSS API integration</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── auth.rs # Session-based authentication with constant-time password verification</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ └── models.rs # Data structures for feeds and FreshRSS responses</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── templates/ # Askama HTML templates</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── assets/ # Static assets embedded at compile time via rust-embed</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── Dockerfile</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">└── docker-compose.yml</span></span></code></pre>\n","isPage":false,"text":"\nfeeds/\n├── src/\n│ ├── main.rs # Axum server with routing, templates, and static asset serving\n│ ├── feeds.rs # Feed fetching, OPML parsing, and FreshRSS API integration\n│ ├── auth.rs # Session-based authentication with constant-time password verification\n│ └── models.rs # Data structures for feeds and FreshRSS responses\n├── templates/ # Askama HTML templates\n├── assets/ # Static assets embedded at compile time via rust-embed\n├── Dockerfile\n└── docker-compose.yml\n","title":"Structure","titles":["Feeds"]},"41":{"href":"/apps/feeds#deployment","html":"\n","isPage":false,"text":"\n","title":"Deployment","titles":["Feeds"]},"42":{"href":"/apps/feeds#railway","html":"\n<p><a href=\"https://railway.com/deploy/Ezvmhx?referralCode=JGcIp6\"><img src=\"https://railway.com/button.svg\" alt=\"Deploy on Railway\"/></a></p>\n","isPage":false,"text":"\n\n","title":"Railway","titles":["Feeds","Deployment"]},"43":{"href":"/apps/feeds#docker","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\">cd</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> apps/feeds</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cp</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> .env.sample</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> .env</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#768390\"># Edit .env with your credentials</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">docker</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> compose</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> up</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -d</span></span></code></pre>\n","isPage":false,"text":"\ncd apps/feeds\ncp .env.sample .env\n# Edit .env with your credentials\ndocker compose up -d\n","title":"Docker","titles":["Feeds","Deployment"]},"44":{"href":"/apps/feeds#binary","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> build</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> --release</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> feeds</span></span></code></pre>\n<p>The resulting binary is self-contained with all assets embedded. Copy it to your server with a configured <code>.env</code> file and run it directly.</p>","isPage":false,"text":"\ncargo build --release -p feeds\nThe resulting binary is self-contained with all assets embedded. Copy it to your server with a configured .env file and run it directly.","title":"Binary","titles":["Feeds","Deployment"]},"45":{"href":"/apps/jotts#jotts","html":"</header>\n<p>A minimal notes app</p>\n","isPage":true,"text":"\nA minimal notes app\n","title":"Jotts","titles":[]},"46":{"href":"/apps/jotts#overview","html":"\n<p>A simple, self-hosted markdown note app built with Rust.</p>\n<ul>\n<li>Single ~7MB Rust binary with embedded assets</li>\n<li>Password authentication with session cookies</li>\n<li>Create, edit, and delete markdown notes</li>\n<li>Markdown rendering with strikethrough, tables, and task lists</li>\n<li>Dark themed UI with Commit Mono font</li>\n<li>SQLite for persistent storage</li>\n</ul>\n","isPage":false,"text":"\nA simple, self-hosted markdown note app built with Rust.\n\nSingle ~7MB Rust binary with embedded assets\nPassword authentication with session cookies\nCreate, edit, and delete markdown notes\nMarkdown rendering with strikethrough, tables, and task lists\nDark themed UI with Commit Mono font\nSQLite for persistent storage\n\n","title":"Overview","titles":["Jotts"]},"47":{"href":"/apps/jotts#quickstart","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">git</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> clone</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> https://github.com/stevedylandev/andromeda.git</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\">cd</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> andromeda</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cp</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> apps/jotts/.env.example</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> .env</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#768390\"># Edit .env with your password</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> run</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> jotts</span></span></code></pre>\n","isPage":false,"text":"\ngit clone https://github.com/stevedylandev/andromeda.git\ncd andromeda\ncp apps/jotts/.env.example .env\n# Edit .env with your password\ncargo run -p jotts\n","title":"Quickstart","titles":["Jotts"]},"48":{"href":"/apps/jotts#environment-variables","html":"\n<table><thead><tr><th>Variable</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>JOTTS_PASSWORD</code></td><td>Password for login authentication</td><td><code>changeme</code></td></tr><tr><td><code>JOTTS_DB_PATH</code></td><td>SQLite database file path</td><td><code>jotts.sqlite</code></td></tr><tr><td><code>HOST</code></td><td>Server bind address</td><td><code>127.0.0.1</code></td></tr><tr><td><code>PORT</code></td><td>Server port</td><td><code>3000</code></td></tr><tr><td><code>COOKIE_SECURE</code></td><td>Enable HTTPS-only cookies</td><td><code>false</code></td></tr></tbody></table>\n","isPage":false,"text":"\nVariableDescriptionDefaultJOTTS_PASSWORDPassword for login authenticationchangemeJOTTS_DB_PATHSQLite database file pathjotts.sqliteHOSTServer bind address127.0.0.1PORTServer port3000COOKIE_SECUREEnable HTTPS-only cookiesfalse\n","title":"Environment Variables","titles":["Jotts","Quickstart"]},"49":{"href":"/apps/jotts#structure","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">jotts/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── src/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── main.rs # App entrypoint, env vars, starts server</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── server.rs # Axum router, HTTP handlers, and templates</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── auth.rs # Password verification and session management</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ └── db.rs # SQLite database layer (notes, sessions)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── templates/ # Askama HTML templates</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── base.html # Base layout with header and nav</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── login.html # Login page</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── index.html # Note list</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── view.html # Single note display</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── new.html # Create note form</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ └── edit.html # Edit note form</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── static/ # Favicons, og:image, styles, and webmanifest</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── assets/ # Commit Mono font files</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── Dockerfile</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">└── docker-compose.yml</span></span></code></pre>\n","isPage":false,"text":"\njotts/\n├── src/\n│ ├── main.rs # App entrypoint, env vars, starts server\n│ ├── server.rs # Axum router, HTTP handlers, and templates\n│ ├── auth.rs # Password verification and session management\n│ └── db.rs # SQLite database layer (notes, sessions)\n├── templates/ # Askama HTML templates\n│ ├── base.html # Base layout with header and nav\n│ ├── login.html # Login page\n│ ├── index.html # Note list\n│ ├── view.html # Single note display\n│ ├── new.html # Create note form\n│ └── edit.html # Edit note form\n├── static/ # Favicons, og:image, styles, and webmanifest\n├── assets/ # Commit Mono font files\n├── Dockerfile\n└── docker-compose.yml\n","title":"Structure","titles":["Jotts"]},"50":{"href":"/apps/jotts#deployment","html":"\n","isPage":false,"text":"\n","title":"Deployment","titles":["Jotts"]},"51":{"href":"/apps/jotts#railway","html":"\n<p><a href=\"https://railway.com/deploy/DLhUhH?referralCode=JGcIp6\"><img src=\"https://railway.com/button.svg\" alt=\"Deploy on Railway\"/></a></p>\n","isPage":false,"text":"\n\n","title":"Railway","titles":["Jotts","Deployment"]},"52":{"href":"/apps/jotts#docker","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\">cd</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> apps/jotts</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cp</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> .env.example</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> .env</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#768390\"># Edit .env with your password</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">docker</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> compose</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> up</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -d</span></span></code></pre>\n<p>This will start Jotts on port <code>3000</code> with a persistent volume for the SQLite database.</p>\n","isPage":false,"text":"\ncd apps/jotts\ncp .env.example .env\n# Edit .env with your password\ndocker compose up -d\nThis will start Jotts on port 3000 with a persistent volume for the SQLite database.\n","title":"Docker","titles":["Jotts","Deployment"]},"53":{"href":"/apps/jotts#binary","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> build</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> --release</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> jotts</span></span></code></pre>\n<p>The resulting binary is self-contained with all assets embedded. Copy it to your server with a configured <code>.env</code> file and run it directly.</p>","isPage":false,"text":"\ncargo build --release -p jotts\nThe resulting binary is self-contained with all assets embedded. Copy it to your server with a configured .env file and run it directly.","title":"Binary","titles":["Jotts","Deployment"]},"54":{"href":"/apps/og#og","html":"</header>\n<p>A simple web tool for inspecting Open Graph tags on any URL.</p>\n","isPage":true,"text":"\nA simple web tool for inspecting Open Graph tags on any URL.\n","title":"OG","titles":[]},"55":{"href":"/apps/og#overview","html":"\n<p>A self-hosted Open Graph tag inspector built with Rust. Enter any URL and instantly see its OG metadata.</p>\n<ul>\n<li>Single Rust binary with embedded assets</li>\n<li>Inspects title, description, image, and other OG tags</li>\n<li>Dark themed UI with Commit Mono font</li>\n<li>No database needed -- fully stateless</li>\n</ul>\n","isPage":false,"text":"\nA self-hosted Open Graph tag inspector built with Rust. Enter any URL and instantly see its OG metadata.\n\nSingle Rust binary with embedded assets\nInspects title, description, image, and other OG tags\nDark themed UI with Commit Mono font\nNo database needed -- fully stateless\n\n","title":"Overview","titles":["OG"]},"56":{"href":"/apps/og#quickstart","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">git</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> clone</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> https://github.com/stevedylandev/andromeda.git</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\">cd</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> andromeda</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> run</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> og</span></span></code></pre>\n","isPage":false,"text":"\ngit clone https://github.com/stevedylandev/andromeda.git\ncd andromeda\ncargo run -p og\n","title":"Quickstart","titles":["OG"]},"57":{"href":"/apps/og#environment-variables","html":"\n<table><thead><tr><th>Variable</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>PORT</code></td><td>Server port</td><td><code>3000</code></td></tr></tbody></table>\n","isPage":false,"text":"\nVariableDescriptionDefaultPORTServer port3000\n","title":"Environment Variables","titles":["OG","Quickstart"]},"58":{"href":"/apps/og#structure","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">og/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── src/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── main.rs # Entry point and server startup</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── server.rs # Axum routes and request handling</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ └── og.rs # Open Graph tag fetching and parsing</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── templates/ # Askama HTML templates</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── base.html # Base layout</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── index.html # Search form</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ └── results.html # OG tag results display</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── static/ # Fonts, favicons, and styles</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── Dockerfile</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">└── docker-compose.yml</span></span></code></pre>\n","isPage":false,"text":"\nog/\n├── src/\n│ ├── main.rs # Entry point and server startup\n│ ├── server.rs # Axum routes and request handling\n│ └── og.rs # Open Graph tag fetching and parsing\n├── templates/ # Askama HTML templates\n│ ├── base.html # Base layout\n│ ├── index.html # Search form\n│ └── results.html # OG tag results display\n├── static/ # Fonts, favicons, and styles\n├── Dockerfile\n└── docker-compose.yml\n","title":"Structure","titles":["OG"]},"59":{"href":"/apps/og#deployment","html":"\n","isPage":false,"text":"\n","title":"Deployment","titles":["OG"]},"60":{"href":"/apps/og#railway","html":"\n<p><a href=\"https://railway.com/deploy/OdXBt_?referralCode=JGcIp6\"><img src=\"https://railway.com/button.svg\" alt=\"Deploy on Railway\"/></a></p>\n","isPage":false,"text":"\n\n","title":"Railway","titles":["OG","Deployment"]},"61":{"href":"/apps/og#docker","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\">cd</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> apps/og</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">docker</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> compose</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> up</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -d</span></span></code></pre>\n","isPage":false,"text":"\ncd apps/og\ndocker compose up -d\n","title":"Docker","titles":["OG","Deployment"]},"62":{"href":"/apps/og#binary","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> build</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> --release</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> og</span></span></code></pre>\n<p>The resulting binary is self-contained with all assets embedded. Copy it to your server and run it directly.</p>","isPage":false,"text":"\ncargo build --release -p og\nThe resulting binary is self-contained with all assets embedded. Copy it to your server and run it directly.","title":"Binary","titles":["OG","Deployment"]},"63":{"href":"/apps/parcels#parcels","html":"</header>\n<p>A minimal package tracking app</p>\n<aside data-callout=\"warning\"><p>This app originally used USPS, but starting April 1st 2026, it has become much harder to obtain/maintain API keys.</p></aside>\n","isPage":true,"text":"\nA minimal package tracking app\nThis app originally used USPS, but starting April 1st 2026, it has become much harder to obtain/maintain API keys.\n","title":"Parcels","titles":[]},"64":{"href":"/apps/parcels#overview","html":"\n<p>A self-hosted package tracker for USPS. Track your packages without logging into USPS every time.</p>\n<ul>\n<li>Single ~7MB Rust binary</li>\n<li>Averages around ~10MB of RAM usage</li>\n<li>Password authentication</li>\n<li>Track USPS packages with custom labels</li>\n<li>Delete packages you no longer want to track</li>\n</ul>\n","isPage":false,"text":"\nA self-hosted package tracker for USPS. Track your packages without logging into USPS every time.\n\nSingle ~7MB Rust binary\nAverages around ~10MB of RAM usage\nPassword authentication\nTrack USPS packages with custom labels\nDelete packages you no longer want to track\n\n","title":"Overview","titles":["Parcels"]},"65":{"href":"/apps/parcels#quickstart","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">git</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> clone</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> https://github.com/stevedylandev/andromeda.git</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\">cd</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> andromeda</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cp</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> apps/parcels/.env.example</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> .env</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#768390\"># Edit .env with your USPS API credentials and app password</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> run</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> parcels</span></span></code></pre>\n<p>You'll need a <a href=\"https://developer.usps.com\">USPS Web Tools API</a> account to get your <code>USPS_CLIENT_ID</code> and <code>USPS_CLIENT_SECRET</code>.</p>\n","isPage":false,"text":"\ngit clone https://github.com/stevedylandev/andromeda.git\ncd andromeda\ncp apps/parcels/.env.example .env\n# Edit .env with your USPS API credentials and app password\ncargo run -p parcels\nYou'll need a USPS Web Tools API account to get your USPS_CLIENT_ID and USPS_CLIENT_SECRET.\n","title":"Quickstart","titles":["Parcels"]},"66":{"href":"/apps/parcels#environment-variables","html":"\n<table><thead><tr><th>Variable</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>APP_PASSWORD</code></td><td>Password for login authentication</td><td><em>required</em></td></tr><tr><td><code>PARCELS_DB_PATH</code></td><td>SQLite database file path</td><td><code>parcels.db</code></td></tr><tr><td><code>USPS_CLIENT_ID</code></td><td>USPS OAuth2 client ID</td><td><em>required</em></td></tr><tr><td><code>USPS_CLIENT_SECRET</code></td><td>USPS OAuth2 client secret</td><td><em>required</em></td></tr><tr><td><code>PORT</code></td><td>Server port</td><td><code>3000</code></td></tr><tr><td><code>COOKIE_SECURE</code></td><td>Enable HTTPS-only cookies</td><td><code>false</code></td></tr></tbody></table>\n","isPage":false,"text":"\nVariableDescriptionDefaultAPP_PASSWORDPassword for login authenticationrequiredPARCELS_DB_PATHSQLite database file pathparcels.dbUSPS_CLIENT_IDUSPS OAuth2 client IDrequiredUSPS_CLIENT_SECRETUSPS OAuth2 client secretrequiredPORTServer port3000COOKIE_SECUREEnable HTTPS-only cookiesfalse\n","title":"Environment Variables","titles":["Parcels","Quickstart"]},"67":{"href":"/apps/parcels#structure","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">parcels/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── src/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── main.rs # Axum web server, routes, and app state</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── auth.rs # Password verification and session management</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── db.rs # SQLite database layer (packages, events, sessions)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ └── usps.rs # USPS API integration with OAuth2 token caching</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── templates/ # Askama HTML templates</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── base.html # Base layout</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── index.html # Package list</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── detail.html # Package detail with tracking events</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── add.html # Add package form</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ └── login.html # Login page</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── static/ # Fonts, favicons, and images</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── Dockerfile</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">└── docker-compose.yml</span></span></code></pre>\n","isPage":false,"text":"\nparcels/\n├── src/\n│ ├── main.rs # Axum web server, routes, and app state\n│ ├── auth.rs # Password verification and session management\n│ ├── db.rs # SQLite database layer (packages, events, sessions)\n│ └── usps.rs # USPS API integration with OAuth2 token caching\n├── templates/ # Askama HTML templates\n│ ├── base.html # Base layout\n│ ├── index.html # Package list\n│ ├── detail.html # Package detail with tracking events\n│ ├── add.html # Add package form\n│ └── login.html # Login page\n├── static/ # Fonts, favicons, and images\n├── Dockerfile\n└── docker-compose.yml\n","title":"Structure","titles":["Parcels"]},"68":{"href":"/apps/parcels#deployment","html":"\n","isPage":false,"text":"\n","title":"Deployment","titles":["Parcels"]},"69":{"href":"/apps/parcels#railway","html":"\n<p><a href=\"https://railway.com/deploy/HNQUs4?referralCode=JGcIp6\"><img src=\"https://railway.com/button.svg\" alt=\"Deploy on Railway\"/></a></p>\n","isPage":false,"text":"\n\n","title":"Railway","titles":["Parcels","Deployment"]},"70":{"href":"/apps/parcels#docker","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\">cd</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> apps/parcels</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cp</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> .env.example</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> .env</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#768390\"># Edit .env with your credentials</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">docker</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> compose</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> up</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -d</span></span></code></pre>\n<p>This will start Parcels on port <code>3000</code> with a persistent volume for the SQLite database.</p>\n","isPage":false,"text":"\ncd apps/parcels\ncp .env.example .env\n# Edit .env with your credentials\ndocker compose up -d\nThis will start Parcels on port 3000 with a persistent volume for the SQLite database.\n","title":"Docker","titles":["Parcels","Deployment"]},"71":{"href":"/apps/parcels#binary","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> build</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> --release</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> parcels</span></span></code></pre>\n<p>The resulting binary is self-contained (~7MB). Copy it to your server with a configured <code>.env</code> file and run it directly.</p>","isPage":false,"text":"\ncargo build --release -p parcels\nThe resulting binary is self-contained (~7MB). Copy it to your server with a configured .env file and run it directly.","title":"Binary","titles":["Parcels","Deployment"]},"72":{"href":"/apps/shrink#shrink","html":"</header>\n<p>A minimal image compression app</p>\n","isPage":true,"text":"\nA minimal image compression app\n","title":"Shrink","titles":[]},"73":{"href":"/apps/shrink#overview","html":"\n<p>A simple self-hosted tool for compressing and resizing images. Upload an image, set your desired quality and optional width, and download the compressed JPEG.</p>\n<ul>\n<li>Single Rust binary</li>\n<li>Compress images to JPEG with configurable quality (1-100)</li>\n<li>Optional resize by width (preserves aspect ratio)</li>\n<li>20MB upload limit</li>\n</ul>\n","isPage":false,"text":"\nA simple self-hosted tool for compressing and resizing images. Upload an image, set your desired quality and optional width, and download the compressed JPEG.\n\nSingle Rust binary\nCompress images to JPEG with configurable quality (1-100)\nOptional resize by width (preserves aspect ratio)\n20MB upload limit\n\n","title":"Overview","titles":["Shrink"]},"74":{"href":"/apps/shrink#quickstart","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">git</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> clone</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> https://github.com/stevedylandev/andromeda.git</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\">cd</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> andromeda</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> run</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> shrink</span></span></code></pre>\n","isPage":false,"text":"\ngit clone https://github.com/stevedylandev/andromeda.git\ncd andromeda\ncargo run -p shrink\n","title":"Quickstart","titles":["Shrink"]},"75":{"href":"/apps/shrink#environment-variables","html":"\n<table><thead><tr><th>Variable</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>HOST</code></td><td>Server bind host</td><td><code>127.0.0.1</code></td></tr><tr><td><code>PORT</code></td><td>Server bind port</td><td><code>3000</code></td></tr></tbody></table>\n","isPage":false,"text":"\nVariableDescriptionDefaultHOSTServer bind host127.0.0.1PORTServer bind port3000\n","title":"Environment Variables","titles":["Shrink","Quickstart"]},"76":{"href":"/apps/shrink#structure","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">shrink/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── src/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── main.rs # Entry point and server startup</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ └── server.rs # Axum routes and image compression logic</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── templates/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ └── index.html # Upload UI</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── static/ # Fonts and static assets</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── Dockerfile</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">└── docker-compose.yml</span></span></code></pre>\n","isPage":false,"text":"\nshrink/\n├── src/\n│ ├── main.rs # Entry point and server startup\n│ └── server.rs # Axum routes and image compression logic\n├── templates/\n│ └── index.html # Upload UI\n├── static/ # Fonts and static assets\n├── Dockerfile\n└── docker-compose.yml\n","title":"Structure","titles":["Shrink"]},"77":{"href":"/apps/shrink#deployment","html":"\n","isPage":false,"text":"\n","title":"Deployment","titles":["Shrink"]},"78":{"href":"/apps/shrink#railway","html":"\n<p><a href=\"https://railway.com/deploy/enYUFb?referralCode=JGcIp6\"><img src=\"https://railway.com/button.svg\" alt=\"Deploy on Railway\"/></a></p>\n","isPage":false,"text":"\n\n","title":"Railway","titles":["Shrink","Deployment"]},"79":{"href":"/apps/shrink#docker","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\">cd</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> apps/shrink</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">docker</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> compose</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> up</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -d</span></span></code></pre>\n<p>This will start Shrink on port <code>3000</code>.</p>\n","isPage":false,"text":"\ncd apps/shrink\ndocker compose up -d\nThis will start Shrink on port 3000.\n","title":"Docker","titles":["Shrink","Deployment"]},"80":{"href":"/apps/shrink#binary","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> build</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> --release</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> shrink</span></span></code></pre>\n<p>The resulting binary is self-contained. Copy it to your server and run it directly.</p>","isPage":false,"text":"\ncargo build --release -p shrink\nThe resulting binary is self-contained. Copy it to your server and run it directly.","title":"Binary","titles":["Shrink","Deployment"]},"81":{"href":"/apps/sipp#sipp","html":"</header>\n<p>Minimal code sharing</p>\n","isPage":true,"text":"\nMinimal code sharing\n","title":"Sipp","titles":[]},"82":{"href":"/apps/sipp#overview","html":"\n<p>A single binary for code sharing with a web server and interactive TUI.</p>\n<ul>\n<li>Create snippets and share on the web</li>\n<li>Raw output for CLI tools -- <code>curl</code>, <code>wget</code>, and <code>httpie</code> get plain text automatically</li>\n<li>Interactive TUI with authenticated access for snippet management</li>\n<li>Minimal, fast, and low memory consumption</li>\n</ul>\n<aside data-callout=\"warning\"><p>A small demo instance runs at <a href=\"https://sipp.so\">sipp.so</a>. All snippets created there are public and might be deleted at any time; host your own instance with your own API key for personal use!</p></aside>\n","isPage":false,"text":"\nA single binary for code sharing with a web server and interactive TUI.\n\nCreate snippets and share on the web\nRaw output for CLI tools -- curl, wget, and httpie get plain text automatically\nInteractive TUI with authenticated access for snippet management\nMinimal, fast, and low memory consumption\n\nA small demo instance runs at sipp.so. All snippets created there are public and might be deleted at any time; host your own instance with your own API key for personal use!\n","title":"Overview","titles":["Sipp"]},"83":{"href":"/apps/sipp#quickstart","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> install</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> sipp-so</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">sipp</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> --help</span></span></code></pre>\n<p>Start a server and create a snippet:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">sipp</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> server</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> --port</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> 3000</span></span></code></pre>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#768390\"># Path to file</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">sipp</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> path/to/file.rs</span></span>\n<span class=\"line\" data-empty-line=\"true\"> </span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#768390\"># Or use the interactive TUI</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">sipp</span></span></code></pre>\n","isPage":false,"text":"\ncargo install sipp-so\nsipp --help\nStart a server and create a snippet:\nsipp server --port 3000\n# Path to file\nsipp path/to/file.rs\n \n# Or use the interactive TUI\nsipp\n","title":"Quickstart","titles":["Sipp"]},"84":{"href":"/apps/sipp#install","html":"\n<p>Sipp can be installed several ways:</p>\n","isPage":false,"text":"\nSipp can be installed several ways:\n","title":"Install","titles":["Sipp","Quickstart"]},"85":{"href":"/apps/sipp#homebrew","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">brew</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> install</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> stevedylandev/tap/sipp-so</span></span></code></pre>\n","isPage":false,"text":"\nbrew install stevedylandev/tap/sipp-so\n","title":"Homebrew","titles":["Sipp","Quickstart","Install"]},"86":{"href":"/apps/sipp#cargo","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> install</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> sipp-so</span></span></code></pre>\n","isPage":false,"text":"\ncargo install sipp-so\n","title":"Cargo","titles":["Sipp","Quickstart","Install"]},"87":{"href":"/apps/sipp#releases","html":"\n<p>Visit the <a href=\"https://github.com/stevedylandev/sipp/releases\">releases</a> page for binaries and install scripts.</p>\n","isPage":false,"text":"\nVisit the releases page for binaries and install scripts.\n","title":"Releases","titles":["Sipp","Quickstart","Install"]},"88":{"href":"/apps/sipp#cli","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">sipp [</span><span style=\"color:#032F62;text-decoration:underline;--shiki-dark:#96D0FF;--shiki-dark-text-decoration:inherit\">OPTIONS</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">] [</span><span style=\"color:#032F62;text-decoration:underline;--shiki-dark:#96D0FF;--shiki-dark-text-decoration:inherit\">FILE</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">] [</span><span style=\"color:#032F62;text-decoration:underline;--shiki-dark:#96D0FF;--shiki-dark-text-decoration:inherit\">COMMAND</span><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">]</span></span></code></pre>\n","isPage":false,"text":"\nsipp [OPTIONS] [FILE] [COMMAND]\n","title":"CLI","titles":["Sipp"]},"89":{"href":"/apps/sipp#commands","html":"\n<table><thead><tr><th>Command</th><th>Description</th></tr></thead><tbody><tr><td><code>server</code></td><td>Start the web server</td></tr><tr><td><code>tui</code></td><td>Launch the interactive TUI</td></tr><tr><td><code>auth</code></td><td>Save remote URL and API key to config file</td></tr></tbody></table>\n","isPage":false,"text":"\nCommandDescriptionserverStart the web servertuiLaunch the interactive TUIauthSave remote URL and API key to config file\n","title":"Commands","titles":["Sipp","CLI"]},"90":{"href":"/apps/sipp#arguments","html":"\n<table><thead><tr><th>Argument</th><th>Description</th></tr></thead><tbody><tr><td><code>[FILE]</code></td><td>File path to create a snippet from</td></tr></tbody></table>\n","isPage":false,"text":"\nArgumentDescription[FILE]File path to create a snippet from\n","title":"Arguments","titles":["Sipp","CLI"]},"91":{"href":"/apps/sipp#options","html":"\n<table><thead><tr><th>Option</th><th>Description</th></tr></thead><tbody><tr><td><code>-r, --remote </code></td><td>Remote server URL (env: <code>SIPP_REMOTE_URL</code>)</td></tr><tr><td><code>-k, --api-key </code></td><td>API key for authenticated operations (env: <code>SIPP_API_KEY</code>)</td></tr></tbody></table>\n","isPage":false,"text":"\nOptionDescription-r, --remote Remote server URL (env: SIPP_REMOTE_URL)-k, --api-key API key for authenticated operations (env: SIPP_API_KEY)\n","title":"Options","titles":["Sipp","CLI"]},"92":{"href":"/apps/sipp#server","html":"\n<p>Sipp includes a built-in web server powered by Axum. Start it with:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">sipp</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> server</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> --port</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> 3000</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> --host</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> localhost</span></span></code></pre>\n","isPage":false,"text":"\nSipp includes a built-in web server powered by Axum. Start it with:\nsipp server --port 3000 --host localhost\n","title":"Server","titles":["Sipp"]},"93":{"href":"/apps/sipp#environment-variables","html":"\n<table><thead><tr><th>Variable</th><th>Description</th></tr></thead><tbody><tr><td><code>SIPP_API_KEY</code></td><td>API key for protecting endpoints</td></tr><tr><td><code>SIPP_AUTH_ENDPOINTS</code></td><td>Comma-separated list of endpoints requiring auth: <code>api_list</code>, <code>api_create</code>, <code>api_get</code>, <code>api_delete</code>, <code>all</code>, or <code>none</code> (defaults to <code>api_delete,api_list</code>)</td></tr><tr><td><code>SIPP_MAX_CONTENT_SIZE</code></td><td>Maximum snippet content size in bytes (defaults to <code>512000</code> / 500 KB)</td></tr><tr><td><code>SIPP_DB_PATH</code></td><td>Custom path for the SQLite database file (defaults to <code>sipp.sqlite</code>)</td></tr></tbody></table>\n","isPage":false,"text":"\nVariableDescriptionSIPP_API_KEYAPI key for protecting endpointsSIPP_AUTH_ENDPOINTSComma-separated list of endpoints requiring auth: api_list, api_create, api_get, api_delete, all, or none (defaults to api_delete,api_list)SIPP_MAX_CONTENT_SIZEMaximum snippet content size in bytes (defaults to 512000 / 500 KB)SIPP_DB_PATHCustom path for the SQLite database file (defaults to sipp.sqlite)\n","title":"Environment Variables","titles":["Sipp","Server"]},"94":{"href":"/apps/sipp#api-endpoints","html":"\n<table><thead><tr><th>Method</th><th>Endpoint</th><th>Description</th></tr></thead><tbody><tr><td><code>GET</code></td><td><code>/api/snippets</code></td><td>List all snippets</td></tr><tr><td><code>POST</code></td><td><code>/api/snippets</code></td><td>Create a snippet (<code>{"name": "...", "content": "..."}</code>)</td></tr><tr><td><code>GET</code></td><td><code>/api/snippets/{short_id}</code></td><td>Get a snippet by ID</td></tr><tr><td><code>PUT</code></td><td><code>/api/snippets/{short_id}</code></td><td>Update a snippet</td></tr><tr><td><code>DELETE</code></td><td><code>/api/snippets/{short_id}</code></td><td>Delete a snippet by ID</td></tr></tbody></table>\n<p>Authenticated endpoints require an <code>x-api-key</code> header.</p>\n","isPage":false,"text":"\nMethodEndpointDescriptionGET/api/snippetsList all snippetsPOST/api/snippetsCreate a snippet ({"name": "...", "content": "..."})GET/api/snippets/{short_id}Get a snippet by IDPUT/api/snippets/{short_id}Update a snippetDELETE/api/snippets/{short_id}Delete a snippet by ID\nAuthenticated endpoints require an x-api-key header.\n","title":"API Endpoints","titles":["Sipp","Server"]},"95":{"href":"/apps/sipp#raw-output-for-cli-tools","html":"\n<p>When you access a snippet URL (<code>/s/{short_id}</code>) with <code>curl</code>, <code>wget</code>, or <code>httpie</code>, the server returns the raw content as plain text instead of HTML:</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">curl</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> https://sipp.so/s/abc123</span></span></code></pre>\n","isPage":false,"text":"\nWhen you access a snippet URL (/s/{short_id}) with curl, wget, or httpie, the server returns the raw content as plain text instead of HTML:\ncurl https://sipp.so/s/abc123\n","title":"Raw Output for CLI Tools","titles":["Sipp","Server"]},"96":{"href":"/apps/sipp#tui","html":"\n<p>The Sipp TUI makes it easy to create, copy, share, and manage your snippets either locally or remotely.</p>\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#768390\"># Launch TUI (default behavior when no file argument is given)</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">sipp</span></span>\n<span class=\"line\" data-empty-line=\"true\"> </span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#768390\"># Or explicitly</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">sipp</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> tui</span></span>\n<span class=\"line\" data-empty-line=\"true\"> </span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#768390\"># With remote options</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">sipp</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -r</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> https://sipp.so</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -k</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> your-api-key</span></span></code></pre>\n","isPage":false,"text":"\nThe Sipp TUI makes it easy to create, copy, share, and manage your snippets either locally or remotely.\n# Launch TUI (default behavior when no file argument is given)\nsipp\n \n# Or explicitly\nsipp tui\n \n# With remote options\nsipp -r https://sipp.so -k your-api-key\n","title":"TUI","titles":["Sipp"]},"97":{"href":"/apps/sipp#local-access","html":"\n<p>If you are running <code>sipp</code> in the same directory as the <code>sipp.sqlite</code> file created by the server instance, the TUI will automatically access the database locally.</p>\n","isPage":false,"text":"\nIf you are running sipp in the same directory as the sipp.sqlite file created by the server instance, the TUI will automatically access the database locally.\n","title":"Local Access","titles":["Sipp","TUI"]},"98":{"href":"/apps/sipp#remote-access","html":"\n<p>To access a remote instance:</p>\n<ul>\n<li>Set the <code>SIPP_API_KEY</code> variable in your server instance</li>\n<li>Run <code>sipp auth</code> to enter your server URL and API key, stored under <code>$HOME/.config/sipp</code></li>\n</ul>\n","isPage":false,"text":"\nTo access a remote instance:\n\nSet the SIPP_API_KEY variable in your server instance\nRun sipp auth to enter your server URL and API key, stored under $HOME/.config/sipp\n\n","title":"Remote Access","titles":["Sipp","TUI"]},"99":{"href":"/apps/sipp#keybindings","html":"\n<table><thead><tr><th>Key</th><th>Action</th></tr></thead><tbody><tr><td><code>j</code>/<code>Down</code></td><td>Move down / Scroll down</td></tr><tr><td><code>k</code>/<code>Up</code></td><td>Move up / Scroll up</td></tr><tr><td><code>Enter</code></td><td>Focus content pane</td></tr><tr><td><code>Esc</code></td><td>Back / Quit</td></tr><tr><td><code>y</code></td><td>Copy snippet content</td></tr><tr><td><code>Y</code></td><td>Copy snippet link</td></tr><tr><td><code>o</code></td><td>Open in browser</td></tr><tr><td><code>e</code></td><td>Edit snippet</td></tr><tr><td><code>d</code></td><td>Delete snippet</td></tr><tr><td><code>c</code></td><td>Create snippet</td></tr><tr><td><code>/</code></td><td>Search snippets</td></tr><tr><td><code>r</code></td><td>Refresh snippets (remote only)</td></tr><tr><td><code>q</code></td><td>Quit</td></tr><tr><td><code>?</code></td><td>Toggle help</td></tr></tbody></table>\n","isPage":false,"text":"\nKeyActionj/DownMove down / Scroll downk/UpMove up / Scroll upEnterFocus content paneEscBack / QuityCopy snippet contentYCopy snippet linkoOpen in browsereEdit snippetdDelete snippetcCreate snippet/Search snippetsrRefresh snippets (remote only)qQuit?Toggle help\n","title":"Keybindings","titles":["Sipp","TUI"]},"100":{"href":"/apps/sipp#structure","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">sipp/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── src/</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── main.rs # CLI argument parsing and entry point</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── lib.rs # Library exports</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── server.rs # Axum web server, routes, and templates</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── tui.rs # Interactive terminal UI</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── db.rs # SQLite database layer</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── backend.rs # Local/remote backend abstraction</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ ├── config.rs # Config file management</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">│ └── highlight.rs # Syntax highlighting with custom themes</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── templates/ # Askama HTML templates</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── static/ # Fonts, favicons, and styles</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">├── Dockerfile</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">└── docker-compose.yml</span></span></code></pre>\n","isPage":false,"text":"\nsipp/\n├── src/\n│ ├── main.rs # CLI argument parsing and entry point\n│ ├── lib.rs # Library exports\n│ ├── server.rs # Axum web server, routes, and templates\n│ ├── tui.rs # Interactive terminal UI\n│ ├── db.rs # SQLite database layer\n│ ├── backend.rs # Local/remote backend abstraction\n│ ├── config.rs # Config file management\n│ └── highlight.rs # Syntax highlighting with custom themes\n├── templates/ # Askama HTML templates\n├── static/ # Fonts, favicons, and styles\n├── Dockerfile\n└── docker-compose.yml\n","title":"Structure","titles":["Sipp"]},"101":{"href":"/apps/sipp#deployment","html":"\n","isPage":false,"text":"\n","title":"Deployment","titles":["Sipp"]},"102":{"href":"/apps/sipp#railway","html":"\n<p><a href=\"https://railway.com/deploy/Axcf_D?referralCode=JGcIp6\"><img src=\"https://railway.com/button.svg\" alt=\"Deploy on Railway\"/></a></p>\n","isPage":false,"text":"\n\n","title":"Railway","titles":["Sipp","Deployment"]},"103":{"href":"/apps/sipp#docker","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#ADBAC7\">SIPP_API_KEY</span><span style=\"color:#D73A49;--shiki-dark:#F47067\">=</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\">your-secret-key</span><span style=\"color:#6F42C1;--shiki-dark:#F69D50\"> docker</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> compose</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> up</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -d</span></span></code></pre>\n","isPage":false,"text":"\nSIPP_API_KEY=your-secret-key docker compose up -d\n","title":"Docker","titles":["Sipp","Deployment"]},"104":{"href":"/apps/sipp#binary","html":"\n<pre class=\"shiki shiki-themes github-light github-dark-dimmed\" style=\"background-color:#fff;--shiki-dark-bg:#22272e;color:#24292e;--shiki-dark:#adbac7\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#F69D50\">cargo</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> build</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> --release</span><span style=\"color:#005CC5;--shiki-dark:#6CB6FF\"> -p</span><span style=\"color:#032F62;--shiki-dark:#96D0FF\"> sipp</span></span></code></pre>\n<p>The resulting binary is self-contained with all assets embedded. Copy it to your server with your environment variables configured and run it directly.</p>","isPage":false,"text":"\ncargo build --release -p sipp\nThe resulting binary is self-contained with all assets embedded. Copy it to your server with your environment variables configured and run it directly.","title":"Binary","titles":["Sipp","Deployment"]}},"dirtCount":0,"index":[["qquit",{"2":{"99":1}}],["quitycopy",{"2":{"99":1}}],["quickstart",{"0":{"0":1,"32":1,"47":1,"56":1,"65":1,"74":1,"83":1},"1":{"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"33":1,"48":1,"57":1,"66":1,"75":1,"84":1,"85":1,"86":1,"87":1}}],["quality",{"2":{"73":2}}],["query",{"0":{"35":1}}],["quot",{"2":{"17":2,"18":32,"23":4,"25":2,"94":8}}],["$home",{"2":{"98":1}}],["x",{"2":{"94":1}}],["x27",{"2":{"4":1,"6":1,"31":2,"65":1}}],["kb",{"2":{"93":1}}],["k",{"2":{"91":1,"96":1}}],["keeping",{"2":{"24":1}}],["key=your",{"2":{"103":1}}],["keyactionj",{"2":{"99":1}}],["keyapi",{"2":{"93":1}}],["keybindings",{"0":{"99":1}}],["keys",{"2":{"63":1}}],["key",{"2":{"13":1,"82":1,"89":1,"91":3,"93":1,"94":1,"96":1,"98":2,"103":1}}],["jpeg",{"2":{"73":2}}],["json",{"2":{"31":1,"39":1}}],["just",{"2":{"31":1}}],["jottsmarkdown",{"2":{"9":1}}],["jotts",{"0":{"45":1},"1":{"46":1,"47":1,"48":1,"49":1,"50":1,"51":1,"52":1,"53":1},"2":{"4":1,"47":2,"49":1,"52":2,"53":1}}],["└──",{"2":{"29":2,"40":2,"49":3,"58":3,"67":3,"76":3,"100":2}}],["│",{"2":{"29":4,"40":4,"49":10,"58":6,"67":9,"76":3,"100":8}}],["├──",{"2":{"29":7,"40":7,"49":13,"58":8,"67":11,"76":5,"100":11}}],["500",{"2":{"93":1}}],["512000",{"2":{"93":1}}],["5",{"0":{"20":1}}],["6",{"2":{"18":1}}],["4",{"0":{"19":1},"2":{"18":1}}],["8",{"2":{"18":2}}],["0",{"2":{"18":8,"48":2,"75":2}}],["32",{"2":{"18":1}}],["3",{"0":{"18":1}}],["3000",{"2":{"4":2,"32":1,"52":1,"70":1,"79":1,"83":1,"92":1}}],["=",{"2":{"17":1,"18":20,"23":1,"25":1}}],["20mb",{"2":{"73":1}}],["2026",{"2":{"63":1}}],["2021",{"2":{"18":1}}],["2",{"0":{"17":1}}],["100",{"2":{"73":1}}],["1st",{"2":{"63":1}}],["1portserver",{"2":{"48":1,"75":1}}],["15",{"2":{"18":1}}],["12",{"2":{"18":1}}],["1",{"0":{"16":1},"2":{"18":3,"73":1}}],["yml",{"2":{"13":1,"29":1,"40":1,"49":1,"58":1,"67":1,"76":1,"100":1}}],["you",{"2":{"8":1,"14":2,"15":1,"29":2,"31":1,"35":3,"36":1,"38":1,"64":1,"65":1,"95":1,"97":1}}],["your",{"0":{"15":1},"1":{"16":1,"17":1,"18":1,"19":1,"20":1},"2":{"5":1,"6":1,"8":2,"12":1,"17":1,"19":1,"33":1,"38":3,"39":1,"43":1,"44":1,"47":1,"52":1,"53":1,"62":1,"64":1,"65":2,"70":1,"71":1,"73":1,"80":1,"82":2,"96":2,"98":2,"104":2}}],["nav",{"2":{"49":1}}],["navigate",{"2":{"29":1}}],["name",{"2":{"5":1,"18":1,"94":1}}],["need",{"2":{"65":1}}],["needed",{"2":{"24":1,"29":1,"55":1}}],["neither",{"2":{"37":1}}],["new",{"2":{"14":1,"15":1,"23":1,"38":1,"49":1}}],["none",{"2":{"93":1}}],["note",{"2":{"46":1,"49":4}}],["notes",{"2":{"45":1,"46":1,"49":1}}],["notesogopen",{"2":{"9":1}}],["no",{"2":{"8":1,"24":1,"26":1,"31":3,"55":1,"64":1,"96":1}}],["~10mb",{"2":{"8":1,"64":1}}],["~7mb",{"2":{"8":1,"46":1,"64":1,"71":1}}],["highlighting",{"2":{"100":1}}],["highlight",{"2":{"100":1}}],["help",{"2":{"83":1,"99":1}}],["header",{"2":{"49":1,"94":1}}],["harder",{"2":{"63":1}}],["has",{"2":{"63":1}}],["have",{"2":{"31":1,"35":1}}],["handlers",{"2":{"29":1,"49":1}}],["handles",{"2":{"25":1,"28":1}}],["handling",{"2":{"23":1,"58":1}}],["html",{"2":{"13":1,"25":2,"29":1,"40":1,"49":7,"58":4,"67":6,"76":1,"95":1,"100":1}}],["httpie",{"2":{"82":1,"95":1}}],["http",{"2":{"4":1,"18":1,"32":1,"49":1}}],["https",{"2":{"2":1,"32":1,"33":1,"35":1,"47":1,"48":1,"56":1,"65":1,"66":1,"74":1,"95":1,"96":1}}],["homebrew",{"0":{"85":1}}],["host",{"2":{"82":1,"92":1}}],["host127",{"2":{"75":1}}],["hosted",{"2":{"7":1,"8":1,"46":1,"55":1,"64":1,"73":1}}],["how",{"2":{"12":1,"19":1,"21":1}}],["display",{"2":{"49":1,"58":1}}],["discover",{"2":{"35":2}}],["directory",{"0":{"16":1},"2":{"25":1,"97":1}}],["directly",{"2":{"6":1,"26":1,"38":1,"44":1,"53":1,"62":1,"71":1,"80":1,"104":1}}],["dark",{"2":{"31":1,"46":1,"55":1}}],["database",{"2":{"13":1,"24":2,"29":1,"48":1,"49":1,"52":1,"55":1,"66":1,"67":1,"70":1,"93":1,"97":1,"100":1}}],["data",{"2":{"8":1,"24":1,"40":1}}],["dbusps",{"2":{"66":1}}],["db",{"2":{"19":1,"29":1,"48":1,"49":1,"66":1,"67":1,"93":1,"100":1}}],["downk",{"2":{"99":1}}],["down",{"2":{"99":1}}],["downmove",{"2":{"99":1}}],["download",{"2":{"73":1}}],["dotenvy",{"2":{"18":1}}],["dockerfile",{"2":{"13":1,"29":1,"40":1,"49":1,"58":1,"67":1,"76":1,"100":1}}],["docker",{"0":{"43":1,"52":1,"61":1,"70":1,"79":1,"103":1},"2":{"6":2,"13":1,"29":1,"40":1,"43":1,"49":1,"52":1,"58":1,"61":1,"67":1,"70":1,"76":1,"79":1,"100":1,"103":1}}],["d",{"2":{"6":1,"43":1,"52":1,"61":1,"70":1,"79":1,"103":1}}],["demo",{"2":{"82":1}}],["desired",{"2":{"73":1}}],["description",{"2":{"55":1}}],["describe",{"2":{"14":1}}],["detail",{"2":{"67":2}}],["deleted",{"2":{"82":1}}],["delete",{"2":{"46":1,"64":1,"93":2,"94":1}}],["dev",{"2":{"35":3}}],["derive",{"2":{"18":1,"25":1}}],["dependencies",{"0":{"22":1},"1":{"23":1,"24":1,"25":1,"26":1,"27":1},"2":{"8":1,"18":1,"21":1,"26":1}}],["deploy",{"2":{"6":1}}],["deployment",{"0":{"6":1,"41":1,"50":1,"59":1,"68":1,"77":1,"101":1},"1":{"42":1,"43":1,"44":1,"51":1,"52":1,"53":1,"60":1,"61":1,"62":1,"69":1,"70":1,"71":1,"78":1,"79":1,"80":1,"102":1,"103":1,"104":1},"2":{"6":1,"8":1,"13":1}}],["defaults",{"2":{"93":3}}],["default",{"2":{"4":1,"37":1,"96":1}}],["terminal",{"2":{"100":1}}],["text",{"2":{"82":1,"95":1}}],["template",{"2":{"25":2}}],["templates",{"2":{"7":1,"13":1,"16":1,"25":3,"29":2,"40":3,"49":3,"58":2,"67":2,"76":1,"100":3}}],["templating",{"2":{"25":1}}],["tuiauthsave",{"2":{"89":1}}],["tui",{"0":{"96":1},"1":{"97":1,"98":1,"99":1},"2":{"82":2,"83":1,"96":3,"97":1,"100":1}}],["tuifeedsrss",{"2":{"9":1}}],["title",{"2":{"55":1}}],["time",{"2":{"8":1,"10":1,"25":1,"26":1,"28":1,"40":2,"64":1,"82":1}}],["tap",{"2":{"85":1}}],["task",{"2":{"46":1}}],["tables",{"2":{"46":1}}],["tags",{"2":{"54":1,"55":1}}],["tag",{"2":{"9":1,"55":1,"58":2}}],["type",{"2":{"25":1}}],["this",{"2":{"12":1,"21":1,"26":1,"29":1,"31":1,"52":1,"63":1,"70":1,"79":1}}],["that",{"2":{"10":1,"13":1,"14":1,"27":1,"28":1,"31":1}}],["there",{"2":{"31":1,"34":1,"82":1}}],["they",{"2":{"21":1}}],["these",{"2":{"15":1}}],["themes",{"2":{"100":1}}],["themed",{"2":{"31":1,"46":1,"55":1}}],["them",{"2":{"4":1,"29":1,"35":1}}],["the",{"0":{"2":1,"14":1,"16":1,"19":1},"2":{"5":1,"6":1,"8":2,"10":1,"12":1,"13":1,"14":3,"15":1,"17":1,"19":1,"21":2,"23":1,"24":1,"26":1,"27":1,"28":1,"31":3,"33":1,"35":3,"36":5,"37":3,"38":2,"39":1,"44":1,"52":1,"53":1,"62":1,"70":1,"71":1,"73":1,"80":1,"82":1,"83":1,"87":1,"89":2,"93":1,"95":2,"96":1,"97":5,"98":1,"104":1}}],["track",{"2":{"64":3}}],["tracker",{"2":{"64":1}}],["tracking",{"2":{"9":1,"63":1,"67":1}}],["transferable",{"2":{"8":1}}],["toggle",{"2":{"99":1}}],["together",{"2":{"21":1}}],["token",{"2":{"67":1}}],["tokio",{"0":{"27":1},"2":{"18":1,"27":1}}],["tools",{"0":{"95":1},"2":{"65":1,"82":1}}],["tool",{"2":{"54":1,"73":1}}],["tower",{"2":{"18":1}}],["toml",{"0":{"18":1},"2":{"17":1}}],["to",{"0":{"17":1},"2":{"6":2,"7":1,"8":1,"12":2,"14":2,"15":2,"17":1,"19":1,"31":1,"34":1,"35":3,"37":1,"38":2,"44":1,"53":1,"62":1,"63":1,"64":1,"65":1,"71":1,"73":1,"80":1,"83":2,"89":1,"90":1,"93":3,"96":1,"98":2,"104":1}}],["ll",{"2":{"65":1}}],["launch",{"2":{"96":1}}],["labels",{"2":{"64":1}}],["layout",{"2":{"49":1,"58":1,"67":1}}],["layer",{"2":{"10":1,"24":1,"29":1,"49":1,"67":1,"100":1}}],["library",{"2":{"100":1}}],["lib",{"2":{"100":1}}],["linkoopen",{"2":{"99":1}}],["limit",{"2":{"73":1}}],["lists",{"2":{"46":1}}],["list",{"2":{"31":1,"49":1,"67":1,"93":3}}],["live",{"2":{"25":1}}],["license",{"0":{"11":1}}],["let",{"2":{"23":1}}],["low",{"2":{"82":1}}],["longer",{"2":{"64":1}}],["logic",{"2":{"76":1}}],["login",{"2":{"10":1,"28":1,"48":1,"49":2,"66":1,"67":2}}],["logging",{"2":{"64":1}}],["locally",{"2":{"96":1,"97":1}}],["local",{"0":{"97":1},"2":{"24":1,"100":1}}],["localhost",{"2":{"4":1,"32":1,"92":1}}],["look",{"2":{"19":1}}],["lt",{"2":{"5":1}}],["url=",{"2":{"37":1}}],["url=https",{"2":{"35":1}}],["urls=https",{"2":{"35":1}}],["urls",{"2":{"35":1}}],["urlurl",{"2":{"33":1}}],["url",{"0":{"35":1},"2":{"31":1,"35":1,"54":1,"55":1,"89":1,"91":2,"95":1,"98":1}}],["under",{"2":{"98":1}}],["understand",{"2":{"29":1}}],["unread",{"2":{"31":1}}],["ui",{"2":{"9":1,"31":1,"46":1,"55":1,"76":1,"100":1}}],["using",{"0":{"14":1},"2":{"12":1,"35":1,"37":1}}],["usps",{"2":{"9":1,"63":1,"64":3,"65":4,"67":2}}],["usage",{"0":{"34":1},"1":{"35":1,"36":1,"37":1,"38":1,"39":1},"2":{"8":1,"64":1}}],["username=",{"2":{"37":1}}],["username",{"2":{"33":1}}],["usernamefreshrss",{"2":{"33":1}}],["used",{"2":{"10":1,"28":1,"63":1}}],["use",{"2":{"5":1,"12":1,"19":1,"82":1,"83":1}}],["upenterfocus",{"2":{"99":1}}],["upmove",{"2":{"99":1}}],["update",{"2":{"94":1}}],["upload",{"2":{"73":2,"76":1}}],["up",{"0":{"18":1},"2":{"0":1,"6":1,"43":1,"52":1,"61":1,"70":1,"79":1,"99":1,"103":1}}],["volume",{"2":{"52":1,"70":1}}],["visit",{"2":{"87":1}}],["view",{"2":{"38":1,"49":1}}],["via",{"2":{"13":1,"28":1,"40":1}}],["vec",{"2":{"25":1}}],["verification",{"2":{"10":1,"28":1,"40":1,"49":1,"67":1}}],["version",{"2":{"1":1,"18":5}}],["variabledescriptionsipp",{"2":{"93":1}}],["variabledescriptiondefaulthostserver",{"2":{"75":1}}],["variabledescriptiondefaultapp",{"2":{"66":1}}],["variabledescriptiondefaultportserver",{"2":{"57":1}}],["variabledescriptiondefaultjotts",{"2":{"48":1}}],["variabledescriptiondefaultfreshrss",{"2":{"33":1}}],["variable",{"2":{"38":1,"98":1}}],["variables",{"0":{"5":1,"33":1,"48":1,"57":1,"66":1,"75":1,"93":1},"2":{"4":1,"37":1,"104":1}}],["vars",{"2":{"29":1,"49":1}}],["var",{"2":{"28":1}}],["values",{"2":{"5":1}}],["either",{"2":{"96":1}}],["easy",{"2":{"96":1}}],["each",{"2":{"4":2,"6":2,"7":1,"8":1,"24":1,"26":1}}],["events",{"2":{"67":2}}],["every",{"2":{"6":1,"8":1,"14":1,"21":1,"23":1,"29":1,"64":1}}],["edit",{"2":{"43":1,"46":1,"47":1,"49":2,"52":1,"65":1,"70":1}}],["edition",{"2":{"18":1}}],["enter",{"2":{"55":1,"98":1}}],["entrypoint",{"2":{"49":1}}],["entry",{"2":{"29":1,"58":1,"76":1,"100":1}}],["endpoints",{"0":{"94":1},"2":{"93":1,"94":1}}],["endpointscomma",{"2":{"93":1}}],["endpointssipp",{"2":{"93":1}}],["endpoint",{"2":{"39":1}}],["enable",{"2":{"38":1}}],["env",{"2":{"5":3,"8":1,"28":1,"29":1,"43":3,"44":1,"47":3,"49":1,"52":3,"53":1,"65":3,"70":3,"71":1,"91":2}}],["environment",{"0":{"5":1,"33":1,"48":1,"57":1,"66":1,"75":1,"93":1},"2":{"4":1,"37":1,"38":1,"104":1}}],["embeds",{"2":{"26":1}}],["embed",{"0":{"26":1},"2":{"13":1,"18":1,"26":1,"40":1}}],["embedded",{"2":{"6":1,"8":1,"13":1,"31":1,"40":1,"44":1,"46":1,"53":1,"55":1,"62":1,"104":1}}],["explicitly",{"2":{"96":1}}],["explains",{"2":{"12":1}}],["exports",{"2":{"39":1,"100":1}}],["export",{"2":{"31":1}}],["experience",{"2":{"31":2}}],["extraction",{"2":{"23":1}}],["external",{"2":{"8":1,"24":1,"26":1}}],["existing",{"2":{"17":1,"19":1}}],["example",{"2":{"5":2,"19":1,"47":1,"52":1,"65":1,"70":1}}],["fast",{"2":{"82":1}}],["favicons",{"2":{"29":1,"49":1,"58":1,"67":1,"100":1}}],["from",{"2":{"38":1,"90":1}}],["framework",{"2":{"23":1}}],["freshrss",{"0":{"37":1},"2":{"9":1,"31":1,"33":3,"37":4,"38":2,"39":1,"40":2}}],["fit",{"2":{"21":1}}],["fill",{"2":{"5":1}}],["files",{"2":{"19":1,"49":1}}],["file",{"0":{"36":1},"2":{"5":2,"8":1,"24":1,"26":1,"31":1,"36":1,"44":1,"48":1,"53":1,"66":1,"71":1,"83":2,"88":1,"89":1,"90":2,"93":1,"96":1,"97":1,"100":1}}],["fully",{"2":{"55":1}}],["full",{"2":{"18":1}}],["fetching",{"2":{"40":1,"58":1}}],["fetch",{"2":{"36":1}}],["feed",{"2":{"31":1,"35":4,"40":1}}],["feeds",{"0":{"30":1,"39":1},"1":{"31":1,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"39":1,"40":1,"41":1,"42":1,"43":1,"44":1},"2":{"4":1,"30":1,"31":2,"32":1,"34":1,"36":2,"38":2,"39":3,"40":3,"43":1,"44":1}}],["features",{"2":{"18":4}}],["font",{"2":{"31":1,"46":1,"49":1,"55":1}}],["fonts",{"2":{"26":1,"29":1,"58":1,"67":1,"76":1,"100":1}}],["following",{"2":{"35":1,"37":1}}],["follow",{"0":{"19":1},"2":{"15":1,"23":1}}],["follows",{"2":{"8":1,"14":1,"29":1}}],["form",{"2":{"49":2,"58":1,"67":1}}],["format=opml",{"2":{"39":1}}],["format=json",{"2":{"39":1}}],["format",{"2":{"39":1}}],["for",{"0":{"95":1},"2":{"4":1,"5":1,"13":1,"19":2,"31":1,"33":1,"36":1,"38":1,"40":1,"46":1,"48":1,"52":1,"54":1,"64":1,"66":1,"70":1,"73":1,"82":4,"87":1,"91":1,"93":2}}],["backend",{"2":{"100":2}}],["base",{"2":{"49":2,"58":2,"67":2}}],["based",{"2":{"10":1,"28":1,"40":1}}],["browsereedit",{"2":{"99":1}}],["brew",{"2":{"85":1}}],["behavior",{"2":{"96":1}}],["be",{"2":{"82":1,"84":1}}],["become",{"2":{"63":1}}],["bearblog",{"2":{"35":3}}],["binaries",{"2":{"87":1}}],["binary",{"0":{"44":1,"53":1,"62":1,"71":1,"80":1,"104":1},"2":{"6":3,"7":1,"8":3,"26":2,"31":1,"44":1,"46":1,"53":1,"55":1,"62":1,"64":1,"71":1,"73":1,"80":1,"82":1,"104":1}}],["bind",{"2":{"48":1,"75":2}}],["but",{"2":{"63":1}}],["buttons",{"2":{"6":1}}],["built",{"2":{"21":1,"34":1,"46":1,"55":1,"92":1}}],["building",{"0":{"15":1},"1":{"16":1,"17":1,"18":1,"19":1,"20":1}}],["build",{"0":{"3":1,"20":1},"2":{"3":1,"12":1,"14":1,"44":1,"53":1,"62":1,"71":1,"80":1,"104":1}}],["bundled",{"2":{"18":1}}],["bytes",{"2":{"93":1}}],["by",{"2":{"4":1,"7":1,"35":1,"73":1,"92":1,"94":2,"97":1}}],["output",{"0":{"95":1},"2":{"82":1}}],["oauth2",{"2":{"66":2,"67":1}}],["obtain",{"2":{"63":1}}],["or",{"2":{"31":2,"39":1,"83":1,"93":1,"95":1,"96":2}}],["originally",{"2":{"63":1}}],["original",{"2":{"31":2}}],["overview",{"0":{"31":1,"46":1,"55":1,"64":1,"73":1,"82":1}}],["other",{"2":{"14":1,"55":1}}],["operations",{"2":{"91":1}}],["open",{"2":{"54":1,"55":1,"58":1}}],["optiondescription",{"2":{"91":1}}],["options",{"0":{"91":1},"2":{"88":1,"96":1}}],["optional",{"2":{"8":1,"73":2}}],["opml",{"0":{"36":1},"2":{"9":1,"31":2,"36":1,"39":1,"40":1}}],["own",{"0":{"15":1},"1":{"16":1,"17":1,"18":1,"19":1,"20":1},"2":{"8":2,"12":1,"24":1,"82":2}}],["only",{"2":{"33":1,"48":1,"66":1,"99":1}}],["once",{"2":{"29":1,"35":1}}],["one",{"2":{"6":1,"8":3,"29":1}}],["on",{"2":{"4":1,"6":1,"8":1,"21":1,"27":1,"31":1,"32":1,"52":1,"54":1,"70":1,"79":1,"82":1}}],["og",{"0":{"54":1},"1":{"55":1,"56":1,"57":1,"58":1,"59":1,"60":1,"61":1,"62":1},"2":{"4":1,"49":1,"55":2,"56":1,"58":3,"61":1,"62":1}}],["of",{"2":{"4":1,"7":1,"8":1,"29":1,"31":2,"33":1,"36":1,"37":1,"64":1,"93":1,"95":1}}],["public",{"2":{"82":1}}],["plain",{"2":{"82":1,"95":1}}],["persistent",{"2":{"46":1,"52":1,"70":1}}],["personal",{"2":{"31":1,"82":1}}],["preserves",{"2":{"73":1}}],["prerequisites",{"0":{"1":1}}],["protecting",{"2":{"93":1}}],["protected",{"2":{"31":1,"38":1}}],["provided",{"2":{"37":1}}],["provides",{"2":{"10":1,"23":1,"24":1,"27":1,"28":1}}],["project",{"2":{"36":1}}],["principles",{"2":{"8":1}}],["philosophy",{"0":{"8":1}}],["point",{"2":{"29":1,"58":1,"76":1,"100":1}}],["posts",{"2":{"31":1,"36":1}}],["post",{"2":{"23":1,"31":2}}],["powering",{"2":{"23":1}}],["powered",{"2":{"7":1,"92":1}}],["port3000",{"2":{"57":1,"75":1}}],["port3000cookie",{"2":{"48":1,"66":1}}],["portable",{"2":{"24":1}}],["port",{"2":{"4":1,"52":1,"70":1,"79":1,"83":1,"92":1}}],["paneescback",{"2":{"99":1}}],["panel",{"0":{"38":1},"2":{"31":1,"33":1,"38":2}}],["parsing",{"2":{"40":1,"58":1,"100":1}}],["param",{"0":{"35":1}}],["params",{"2":{"31":1}}],["parcels",{"0":{"63":1},"1":{"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1},"2":{"4":1,"65":2,"67":1,"70":2,"71":1}}],["pathcustom",{"2":{"93":1}}],["pathparcels",{"2":{"66":1}}],["pathjotts",{"2":{"48":1}}],["pathsqlite",{"2":{"48":1,"66":1}}],["path",{"2":{"25":1,"83":2,"90":1,"93":1}}],["pattern",{"0":{"19":1,"29":1},"2":{"23":1}}],["patterns",{"2":{"8":1,"14":1}}],["packages",{"2":{"64":3,"67":1}}],["package",{"2":{"18":1,"63":1,"64":1,"67":3}}],["password=",{"2":{"37":1}}],["passwordpassword",{"2":{"33":1,"48":1,"66":1}}],["passwordfreshrss",{"2":{"33":1}}],["password",{"2":{"10":2,"28":2,"31":1,"33":1,"38":2,"40":1,"46":1,"47":1,"49":1,"52":1,"64":1,"65":1,"67":1}}],["page",{"2":{"4":1,"6":1,"12":1,"19":1,"21":1,"49":1,"67":1,"87":1}}],["p",{"2":{"4":7,"16":3,"20":1,"32":1,"44":1,"47":1,"53":1,"56":1,"62":1,"65":1,"71":1,"74":1,"80":1,"104":1}}],["r",{"2":{"91":1,"96":1}}],["rss",{"2":{"30":1,"31":2,"34":1,"35":1}}],["rs",{"2":{"19":3,"29":4,"40":4,"49":4,"58":3,"67":4,"76":2,"83":1,"100":8}}],["routes",{"2":{"29":1,"58":1,"67":1,"76":1,"100":1}}],["route",{"2":{"23":2}}],["router",{"2":{"23":1,"49":1}}],["routing",{"2":{"13":1,"23":1,"40":1}}],["root",{"2":{"17":1,"36":1}}],["raw",{"0":{"95":1},"2":{"82":1,"95":1}}],["ratio",{"2":{"73":1}}],["ram",{"2":{"8":1,"64":1}}],["railway",{"0":{"42":1,"51":1,"60":1,"69":1,"78":1,"102":1},"2":{"6":1}}],["returns",{"2":{"95":1}}],["remotely",{"2":{"96":1}}],["remote",{"0":{"98":1},"2":{"89":1,"91":3,"96":1,"98":1,"99":1,"100":1}}],["rendering",{"2":{"46":1}}],["reading",{"2":{"31":1}}],["read",{"2":{"31":2}}],["reader",{"2":{"9":1,"31":1}}],["requiring",{"2":{"93":1}}],["require",{"2":{"10":1,"28":1,"94":1}}],["request",{"2":{"23":1,"58":1}}],["reference",{"2":{"19":1}}],["resize",{"2":{"73":1}}],["resizing",{"2":{"9":1,"73":1}}],["results",{"2":{"58":2}}],["resulting",{"2":{"44":1,"53":1,"62":1,"71":1,"80":1,"104":1}}],["responses",{"2":{"40":1}}],["response",{"2":{"23":1}}],["resource",{"2":{"8":1}}],["releases",{"0":{"87":1},"2":{"87":1}}],["release",{"2":{"3":1,"44":1,"53":1,"62":1,"71":1,"80":1,"104":1}}],["rusqlite",{"0":{"24":1},"2":{"13":1,"18":1,"24":1}}],["rustc",{"2":{"1":1}}],["rust",{"0":{"13":1,"26":1},"2":{"1":1,"7":1,"8":1,"12":1,"13":3,"14":1,"18":1,"21":1,"25":1,"26":1,"31":1,"40":1,"46":2,"55":2,"64":1,"73":1}}],["runs",{"2":{"27":1,"82":1}}],["runtime",{"2":{"27":1}}],["run",{"0":{"4":1,"20":1},"2":{"4":8,"6":1,"8":1,"20":1,"32":1,"44":1,"47":1,"53":1,"56":1,"62":1,"65":1,"71":1,"74":1,"80":1,"98":1,"104":1}}],["running",{"2":{"0":1,"32":1,"35":1,"97":1}}],["syntax",{"2":{"100":1}}],["scroll",{"2":{"99":2}}],["scripts",{"2":{"87":1}}],["scaffolds",{"2":{"13":1}}],["scaffolded",{"2":{"12":1}}],["snippetccreate",{"2":{"99":1}}],["snippetddelete",{"2":{"99":1}}],["snippetdelete",{"2":{"94":1}}],["snippet",{"2":{"82":1,"83":1,"90":1,"93":1,"94":3,"95":1,"99":3}}],["snippetsrrefresh",{"2":{"99":1}}],["snippetscreate",{"2":{"94":1}}],["snippetspost",{"2":{"94":1}}],["snippetslist",{"2":{"94":1}}],["snippets",{"2":{"82":2,"94":3,"96":1,"99":1}}],["sample",{"2":{"43":1}}],["same",{"2":{"8":2,"12":1,"14":1,"21":1,"97":1}}],["save",{"2":{"36":1}}],["safe",{"2":{"25":1}}],["src",{"2":{"16":1,"29":1,"40":1,"49":1,"58":1,"67":1,"76":1,"100":1}}],["skill",{"0":{"14":1},"2":{"12":1,"13":1,"14":2}}],["skills",{"0":{"12":1},"1":{"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1}}],["source",{"2":{"34":1,"35":1,"36":1}}],["sources",{"2":{"31":1}}],["so",{"2":{"8":1,"82":1,"83":1,"85":1,"86":1,"95":1,"96":1}}],["short",{"2":{"94":3,"95":1}}],["sharing",{"2":{"9":1,"81":1,"82":1}}],["shared",{"0":{"10":1,"28":1},"2":{"10":1}}],["share",{"2":{"8":1,"82":1,"96":1}}],["shrink",{"0":{"72":1},"1":{"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1},"2":{"4":1,"74":1,"76":1,"79":2,"80":1}}],["small",{"2":{"8":1,"82":1}}],["sqlitehostserver",{"2":{"48":1}}],["sqlite",{"0":{"24":1},"2":{"7":1,"13":1,"24":1,"29":1,"46":1,"49":1,"52":1,"67":1,"70":1,"93":2,"97":1,"100":1}}],["secretrequiredportserver",{"2":{"66":1}}],["secretusps",{"2":{"66":1}}],["secret",{"2":{"65":1,"103":1}}],["secureenable",{"2":{"33":1,"48":1,"66":1}}],["secure",{"2":{"28":2}}],["search",{"2":{"58":1,"99":1}}],["see",{"2":{"55":1}}],["separated",{"2":{"93":1}}],["separate",{"2":{"35":1}}],["several",{"2":{"34":1,"84":1}}],["serving",{"2":{"40":1}}],["servertuilaunch",{"2":{"89":1}}],["server",{"0":{"92":1},"1":{"93":1,"94":1,"95":1},"2":{"4":1,"6":1,"13":1,"19":1,"24":1,"29":2,"32":1,"40":1,"44":1,"49":2,"53":1,"58":2,"62":1,"67":1,"71":1,"76":2,"80":1,"82":1,"83":2,"91":1,"92":2,"95":1,"97":1,"98":2,"100":2,"104":1}}],["serde",{"2":{"18":1}}],["set",{"0":{"18":1},"2":{"37":1,"38":1,"73":1,"98":1}}],["sessions",{"2":{"49":1,"67":1}}],["session",{"2":{"10":1,"28":2,"40":1,"46":1,"49":1,"67":1}}],["self",{"2":{"7":1,"8":1,"26":1,"44":1,"46":1,"53":1,"55":1,"62":1,"64":1,"71":1,"73":1,"80":1,"104":1}}],["subscriptions",{"2":{"31":1,"38":2,"39":1}}],["supportparcelspackage",{"2":{"9":1}}],["supports",{"2":{"6":1}}],["sure",{"2":{"1":1}}],["size",{"2":{"93":1}}],["sizemaximum",{"2":{"93":1}}],["similar",{"2":{"23":1}}],["simple",{"2":{"8":1,"46":1,"54":1,"73":1}}],["single",{"2":{"6":1,"7":1,"8":1,"26":1,"31":1,"46":1,"49":1,"55":1,"64":1,"73":1,"82":1}}],["sipp",{"0":{"81":1},"1":{"82":1,"83":1,"84":1,"85":1,"86":1,"87":1,"88":1,"89":1,"90":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"102":1,"103":1,"104":1},"2":{"4":1,"82":1,"83":5,"84":1,"85":1,"86":1,"88":1,"91":2,"92":2,"93":3,"95":1,"96":5,"97":2,"98":3,"100":1,"103":1,"104":1}}],["s",{"2":{"4":1,"6":1,"31":2,"95":2}}],["stored",{"2":{"98":1}}],["storage",{"2":{"24":1,"46":1}}],["strikethrough",{"2":{"46":1}}],["struct",{"2":{"25":1}}],["structs",{"2":{"25":1}}],["structures",{"2":{"40":1}}],["structure",{"0":{"40":1,"49":1,"58":1,"67":1,"76":1,"100":1},"2":{"19":1,"29":1}}],["straightforward",{"2":{"6":1}}],["stevedylan",{"2":{"35":1}}],["stevedylandev",{"2":{"2":1,"32":1,"47":1,"56":1,"65":1,"74":1,"85":1}}],["steps",{"2":{"15":1}}],["styles",{"2":{"29":1,"49":1,"58":1,"100":1}}],["style",{"2":{"12":1}}],["stateless",{"2":{"55":1}}],["state",{"2":{"23":2,"67":1}}],["static",{"2":{"13":1,"16":1,"26":1,"29":1,"40":2,"49":1,"58":1,"67":1,"76":2,"100":1}}],["stack",{"0":{"21":1},"1":{"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1},"2":{"8":2,"13":1,"19":1,"21":1}}],["starting",{"2":{"63":1}}],["startup",{"2":{"58":1,"76":1}}],["starts",{"2":{"29":1,"49":1}}],["start",{"2":{"4":1,"52":1,"70":1,"79":1,"83":1,"92":1}}],["specific",{"0":{"4":1},"2":{"4":1}}],["curl",{"2":{"82":1,"95":2}}],["current",{"2":{"38":1}}],["custom",{"2":{"12":1,"64":1,"100":1}}],["css",{"2":{"26":1}}],["credentials",{"2":{"43":1,"65":1,"70":1}}],["created",{"2":{"82":1,"97":1}}],["creates",{"2":{"24":1}}],["create",{"0":{"16":1},"2":{"14":1,"23":1,"46":1,"49":1,"82":1,"83":1,"90":1,"93":1,"96":1}}],["crud",{"0":{"13":1},"2":{"12":1,"13":2,"14":1}}],["crate",{"0":{"28":1},"2":{"10":1,"28":1}}],["cratedescriptionandromeda",{"2":{"10":1}}],["crates",{"0":{"10":1}}],["caching",{"2":{"67":1}}],["categories",{"2":{"31":1}}],["can",{"2":{"29":1,"35":2,"38":1,"84":1}}],["called",{"2":{"12":1}}],["cargo",{"0":{"18":1,"86":1},"2":{"3":1,"4":7,"17":1,"20":1,"32":1,"44":1,"47":1,"53":1,"56":1,"62":1,"65":1,"71":1,"74":1,"80":1,"83":1,"86":1,"104":1}}],["cli",{"0":{"88":1,"95":1},"1":{"89":1,"90":1,"91":1},"2":{"82":1,"100":1}}],["client",{"2":{"65":2,"66":4}}],["click",{"2":{"6":1}}],["claude",{"2":{"12":1,"13":1,"14":1}}],["clone",{"0":{"2":1},"2":{"2":1,"32":1,"47":1,"56":1,"65":1,"74":1}}],["cp",{"2":{"5":1,"43":1,"47":1,"52":1,"65":1,"70":1}}],["cookie",{"2":{"28":3,"33":1}}],["cookiesfalse",{"2":{"33":1,"48":1,"66":1}}],["cookies",{"2":{"10":1,"46":1}}],["core",{"0":{"22":1},"1":{"23":1,"24":1,"25":1,"26":1,"27":1},"2":{"21":1}}],["cors",{"2":{"18":1}}],["covers",{"2":{"21":1}}],["code",{"2":{"12":1,"13":1,"14":1,"81":1,"82":1}}],["config",{"2":{"89":1,"98":1,"100":2}}],["configurable",{"2":{"73":1}}],["configuration",{"2":{"4":1,"5":1,"28":1}}],["configured",{"2":{"44":1,"53":1,"71":1,"104":1}}],["contentycopy",{"2":{"99":1}}],["content",{"2":{"93":2,"94":1,"95":1,"99":1}}],["context",{"2":{"31":1}}],["contained",{"2":{"26":1,"44":1,"53":1,"62":1,"71":1,"80":1,"104":1}}],["consumption",{"2":{"82":1}}],["consistency",{"2":{"29":1}}],["consistent",{"2":{"8":1,"29":1}}],["constant",{"2":{"10":1,"28":1,"40":1}}],["copy",{"2":{"5":1,"6":1,"44":1,"53":1,"62":1,"71":1,"80":1,"96":1,"104":1}}],["commanddescriptionserverstart",{"2":{"89":1}}],["commands",{"0":{"89":1}}],["command",{"2":{"88":1}}],["commas",{"2":{"35":1}}],["commit",{"2":{"31":1,"46":1,"49":1,"55":1}}],["compress",{"2":{"73":1}}],["compressed",{"2":{"73":1}}],["compressing",{"2":{"73":1}}],["compression",{"2":{"9":1,"72":1,"76":1}}],["complete",{"2":{"13":1,"14":1}}],["compile",{"2":{"8":1,"25":1,"26":1,"40":1}}],["compiles",{"2":{"6":1,"7":1,"8":1}}],["compose",{"2":{"6":1,"13":1,"29":1,"40":1,"43":1,"49":1,"52":1,"58":1,"61":1,"67":1,"70":1,"76":1,"79":1,"100":1,"103":1}}],["com",{"2":{"2":1,"32":1,"47":1,"56":1,"65":1,"74":1}}],["checked",{"2":{"25":1}}],["check",{"2":{"4":1}}],["cd",{"2":{"2":1,"32":1,"43":1,"47":1,"52":1,"56":1,"61":1,"65":1,"70":1,"74":1,"79":1}}],["given",{"2":{"96":1}}],["github",{"2":{"2":1,"32":1,"47":1,"56":1,"65":1,"74":1}}],["git",{"2":{"2":2,"32":2,"47":2,"56":2,"65":2,"74":2}}],["generate",{"2":{"14":1}}],["get",{"2":{"0":1,"23":1,"65":1,"82":1,"93":1,"94":2}}],["graph",{"2":{"9":1,"54":1,"55":1,"58":1}}],["gt",{"2":{"5":1}}],["wget",{"2":{"82":1,"95":1}}],["ways",{"2":{"34":1,"84":1}}],["want",{"2":{"14":2,"15":1,"64":1}}],["working",{"2":{"14":1,"19":1}}],["workspace",{"0":{"2":1,"17":1},"2":{"4":1,"7":1,"15":1,"17":2}}],["width",{"2":{"73":2}}],["will",{"2":{"14":1,"36":1,"37":1,"52":1,"70":1,"79":1,"97":1}}],["without",{"2":{"64":1}}],["with",{"2":{"0":1,"4":1,"6":1,"8":1,"9":2,"12":1,"13":2,"23":1,"25":1,"26":1,"31":4,"40":2,"43":1,"44":2,"46":5,"47":1,"49":1,"52":2,"53":2,"55":3,"62":1,"64":1,"65":1,"67":2,"70":2,"71":1,"73":1,"82":3,"92":1,"95":1,"96":1,"100":1,"104":2}}],["when",{"2":{"14":1,"95":1,"96":1}}],["what",{"0":{"7":1,"13":1},"1":{"8":1,"9":1,"10":1,"11":1},"2":{"14":1,"26":1}}],["webmanifest",{"2":{"49":1}}],["website",{"2":{"31":1}}],["web",{"2":{"7":1,"9":1,"13":2,"23":1,"54":1,"65":1,"67":1,"82":2,"89":1,"92":1,"100":1}}],["idput",{"2":{"94":1}}],["idrequiredusps",{"2":{"66":1}}],["idusps",{"2":{"66":1}}],["id",{"2":{"65":1,"94":4,"95":1}}],["image",{"2":{"49":1,"55":1,"72":1,"73":1,"76":1}}],["images",{"2":{"26":1,"67":1,"73":2}}],["if",{"2":{"15":1,"29":1,"36":1,"37":1,"97":1}}],["its",{"2":{"24":1,"31":1,"55":1}}],["item",{"2":{"23":1}}],["items",{"2":{"23":1,"25":1}}],["it",{"2":{"6":1,"8":1,"12":1,"23":1,"28":1,"31":2,"36":1,"38":1,"44":2,"53":2,"62":2,"63":1,"71":2,"80":2,"92":1,"96":1,"104":2}}],["is",{"0":{"7":1,"13":1},"1":{"8":1,"9":1,"10":1,"11":1},"2":{"1":1,"4":1,"7":1,"13":1,"21":1,"23":1,"26":1,"31":2,"44":1,"53":1,"62":1,"71":1,"80":1,"96":1,"104":1}}],["interactive",{"2":{"82":2,"83":1,"89":1,"100":1}}],["integration",{"2":{"40":1,"67":1}}],["into",{"2":{"26":1,"64":1}}],["includes",{"2":{"38":1,"92":1}}],["including",{"2":{"10":1}}],["indextemplate",{"2":{"25":1}}],["index",{"2":{"23":1,"25":1,"49":1,"58":1,"67":1,"76":1}}],["invoke",{"2":{"14":1}}],["instead",{"2":{"95":1}}],["install",{"0":{"84":1},"1":{"85":1,"86":1,"87":1},"2":{"83":1,"85":1,"86":1,"87":1}}],["installed",{"2":{"1":1,"84":1}}],["instantly",{"2":{"55":1}}],["instance",{"2":{"33":1,"37":1,"38":1,"82":2,"97":1,"98":2}}],["inspects",{"2":{"55":1}}],["inspector",{"2":{"55":1}}],["inspectorshrinkimage",{"2":{"9":1}}],["inspecting",{"2":{"54":1}}],["inside",{"2":{"36":1}}],["infrastructure",{"2":{"8":1}}],["in",{"2":{"0":1,"5":1,"8":1,"12":1,"14":1,"19":1,"21":1,"25":1,"31":2,"34":1,"36":1,"39":1,"92":1,"93":1,"97":1,"98":1,"99":1}}],["much",{"2":{"63":1}}],["multiple",{"2":{"31":1,"35":1}}],["models",{"2":{"40":1}}],["mono",{"2":{"31":1,"46":1,"49":1,"55":1}}],["most",{"2":{"4":1,"5":1}}],["methodendpointdescriptionget",{"2":{"94":1}}],["metadata",{"2":{"55":1}}],["memory",{"2":{"82":1}}],["members",{"2":{"17":2}}],["member",{"2":{"4":1}}],["means",{"2":{"29":1}}],["my",{"2":{"16":3,"17":1,"18":1,"20":1}}],["mkdir",{"2":{"16":3}}],["max",{"2":{"93":1}}],["markdown",{"2":{"46":3}}],["marking",{"2":{"31":1}}],["manage",{"2":{"96":1}}],["management",{"2":{"28":1,"49":1,"67":1,"82":1,"100":1}}],["managing",{"2":{"31":1,"38":1}}],["manually",{"2":{"15":1}}],["maintain",{"2":{"63":1}}],["main",{"2":{"19":1,"29":1,"40":1,"49":1,"58":1,"67":1,"76":1,"100":1}}],["matching",{"2":{"13":1}}],["making",{"2":{"6":1}}],["makes",{"2":{"26":1,"96":1}}],["make",{"2":{"1":1}}],["might",{"2":{"82":1}}],["mimics",{"2":{"31":1}}],["middleware",{"2":{"23":1}}],["mit",{"2":{"11":1}}],["minimal",{"2":{"7":1,"8":1,"30":1,"31":1,"45":1,"63":1,"72":1,"81":1,"82":1}}],["minutes",{"2":{"0":1}}],["abstraction",{"2":{"100":1}}],["abc123",{"2":{"95":1}}],["above",{"2":{"37":1}}],["access",{"0":{"97":1,"98":1},"2":{"82":1,"95":1,"97":1,"98":1}}],["account",{"2":{"65":1}}],["across",{"2":{"10":1,"28":1}}],["automatically",{"2":{"36":1,"82":1,"97":1}}],["authenticated",{"2":{"82":1,"91":1,"94":1}}],["authenticationrequiredparcels",{"2":{"66":1}}],["authenticationchangemejotts",{"2":{"48":1}}],["authentication",{"2":{"10":2,"13":1,"28":1,"29":1,"40":1,"46":1,"64":1}}],["author",{"2":{"31":1}}],["auth",{"0":{"28":1},"2":{"10":1,"28":1,"29":1,"40":1,"49":1,"67":1,"93":2,"98":1}}],["authsession",{"2":{"10":1}}],["also",{"2":{"35":1}}],["all",{"0":{"3":1},"2":{"8":2,"23":1,"44":1,"53":1,"62":1,"82":1,"93":1,"94":1,"104":1}}],["admin",{"0":{"38":1},"2":{"31":1,"33":2,"38":4}}],["address127",{"2":{"48":1}}],["add",{"0":{"17":1},"2":{"15":1,"17":1,"35":2,"38":1,"67":2}}],["april",{"2":{"63":1}}],["api",{"0":{"37":1,"39":1,"94":1},"2":{"13":1,"23":1,"31":2,"37":1,"40":1,"63":1,"65":2,"67":1,"82":1,"89":1,"91":3,"93":7,"94":6,"96":1,"98":2,"103":1}}],["approach",{"2":{"31":1}}],["application",{"2":{"13":1}}],["appdescriptionsippcode",{"2":{"9":1}}],["apps",{"0":{"3":1,"9":1},"2":{"4":1,"5":2,"7":1,"8":2,"10":1,"12":2,"16":3,"17":2,"19":1,"23":1,"28":1,"43":1,"47":1,"52":1,"61":1,"65":1,"70":1,"79":1}}],["app",{"0":{"4":1,"15":1,"16":1,"29":1},"1":{"16":1,"17":1,"18":1,"19":1,"20":1},"2":{"0":1,"4":2,"5":1,"6":3,"7":1,"8":2,"14":3,"15":1,"16":3,"17":2,"18":1,"19":1,"20":1,"21":1,"23":3,"24":1,"26":1,"29":3,"31":1,"35":1,"36":1,"37":1,"45":1,"46":1,"49":1,"63":2,"65":1,"67":1,"72":1}}],["argument",{"2":{"96":1,"100":1}}],["argumentdescription",{"2":{"90":1}}],["arguments",{"0":{"90":1}}],["are",{"2":{"8":1,"12":1,"25":1,"34":1,"37":1,"82":1,"97":1}}],["around",{"2":{"8":1,"64":1}}],["averages",{"2":{"64":1}}],["average",{"2":{"8":1}}],["at",{"2":{"8":1,"19":1,"26":1,"38":1,"40":1,"82":2}}],["aspect",{"2":{"73":1}}],["asset",{"2":{"40":1}}],["assets",{"2":{"6":1,"8":1,"13":1,"26":1,"31":1,"40":2,"44":1,"46":1,"49":1,"53":1,"55":1,"62":1,"76":1,"104":1}}],["async",{"2":{"27":1}}],["as",{"2":{"14":1,"19":1,"95":1,"97":1}}],["askama",{"0":{"25":1},"2":{"7":1,"13":1,"18":2,"25":1,"29":1,"40":1,"49":1,"58":1,"67":1,"100":1}}],["axum",{"0":{"23":1},"2":{"7":1,"13":1,"18":2,"23":1,"27":1,"29":1,"40":1,"49":1,"58":1,"67":1,"76":1,"92":1,"100":1}}],["a",{"0":{"4":1},"2":{"4":1,"5":1,"6":1,"7":2,"10":1,"12":1,"13":2,"14":2,"15":1,"19":2,"23":1,"25":1,"26":1,"29":1,"31":3,"36":1,"37":1,"38":1,"44":1,"45":1,"46":1,"52":1,"53":1,"54":1,"55":1,"63":1,"64":1,"65":1,"70":1,"71":1,"72":1,"73":1,"82":3,"83":2,"90":1,"92":1,"94":4,"95":1,"98":1}}],["an",{"2":{"35":1,"73":1,"94":1}}],["any",{"2":{"0":1,"4":1,"19":1,"29":1,"54":1,"55":1,"82":1}}],["andromeda",{"0":{"7":1,"28":1},"1":{"8":1,"9":1,"10":1,"11":1},"2":{"0":1,"2":2,"7":1,"8":1,"10":1,"12":1,"13":1,"14":1,"21":1,"28":1,"32":2,"47":2,"56":2,"65":2,"74":2}}],["and",{"0":{"20":1},"2":{"0":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":3,"10":1,"13":1,"14":1,"19":1,"21":1,"23":1,"24":1,"25":1,"29":1,"31":3,"36":1,"38":1,"40":3,"44":1,"46":2,"49":4,"53":1,"55":2,"58":4,"62":1,"65":2,"67":3,"71":1,"73":3,"76":3,"80":1,"82":5,"83":1,"87":1,"89":1,"96":1,"98":1,"100":3,"104":1}}]],"serializationVersion":2} |
Binary file — no preview.
Binary file — no preview.
| 1 | + | <!doctype html> |
|
| 2 | + | <html lang="en" class="dark" data-vocs> |
|
| 3 | + | <head> |
|
| 4 | + | <meta charset="UTF-8" /> |
|
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
| 6 | + | <script src="/initializeTheme.iife.js"></script><link rel="preload" as="image" href="https://railway.com/button.svg"/><title>Feeds – Andromeda</title><meta property="og:type" content="website"/><meta property="og:title" content="Feeds"/><meta name="twitter:card" content="summary_large_image"/> |
|
| 7 | + | <script type="module" crossorigin src="/assets/index-DO6OtFZH.js"></script> |
|
| 8 | + | <link rel="stylesheet" crossorigin href="/assets/style-Dg8GuVX0.css"> |
|
| 9 | + | </head> |
|
| 10 | + | <body> |
|
| 11 | + | <span style="display: none;">Are you an LLM? Read <a href="/llms.txt">llms.txt</a> for a summary of the docs, or <a href="/llms-full.txt">llms-full.txt</a> for the full context.</span> |
|
| 12 | + | <div id="app"><div class="vocs_DocsLayout" data-layout="docs"><a class="vocs_SkipLink vocs_utils_visuallyHidden" href="/apps/feeds#vocs-content">Skip to content</a><div class="vocs_DocsLayout_gutterLeft"><aside class="vocs_Sidebar vocs_DocsLayout_sidebar"><div><div class="vocs_Sidebar_logoWrapper"><div class="vocs_Sidebar_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div><div class="vocs_Sidebar_divider"></div></div><nav class="vocs_Sidebar_navigation"><div class="vocs_Sidebar_group"><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Intro</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/quickstart" data-discover="true">Quickstart</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/what-is-andromeda" data-discover="true">What is Andromeda</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Apps</div></div><div class="vocs_Sidebar_items"><a data-active="true" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/feeds" data-discover="true">Feeds</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/jotts" data-discover="true">Jotts</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/sipp" data-discover="true">Sipp</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/og" data-discover="true">OG</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/shrink" data-discover="true">Shrink</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/parcels" data-discover="true">Parcels</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">DIY</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/stack" data-discover="true">Stack</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/skills" data-discover="true">Skills</a></div></section></div></nav></div><div class="vocs_Sidebar_footer"><div class="vocs_Sidebar_footerCurtain"></div><div class="vocs_Sidebar_footerContent"></div></div></aside></div><div class="vocs_DocsLayout_gutterTop vocs_DocsLayout_gutterTop_offsetLeftGutter"><div class="vocs_DesktopTopNav"><button class="vocs_DesktopSearch_search" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_4lj_" data-state="closed"><svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-top:2px"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>Search...<div class="vocs_DesktopSearch_searchCommand"><div style="background:currentColor;transform:rotate(45deg);width:1.5px;border-radius:2px;height:100%"></div></div></button><div class="vocs_DesktopTopNav_logoWrapper"><div class="vocs_DesktopTopNav_logo"><a style="align-items:center;display:flex;height:56px;margin-top:4px" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_DesktopTopNav_section"></div><div class="vocs_DesktopTopNav_section"></div></div><div class="vocs_MobileTopNav"><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group"><div class="vocs_MobileTopNav_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_MobileTopNav_group"><nav aria-label="Main" data-orientation="horizontal" dir="ltr" class="vocs_MobileTopNav_navigation vocs_NavigationMenu"><div style="position:relative"><ul data-orientation="horizontal" class="vocs_NavigationMenu_list" dir="ltr"></ul></div></nav><div class="vocs_MobileTopNav_navigation vocs_MobileTopNav_navigation_compact"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_kpj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger vocs_MobileTopNav_navigationItem">Menu<div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group" style="margin-right:-8px"><button class="vocs_MobileSearch_searchButton" type="button" aria-label="Search" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_39j_" data-state="closed"><svg width="21" height="21" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div></div></div></div><div class="vocs_DocsLayout_gutterTopCurtain vocs_DocsLayout_gutterTopCurtain_withSidebar"><div class="vocs_DesktopTopNav_curtain"></div><div class="vocs_MobileTopNav_curtain"><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_qj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger"><div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:13px"><svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 79 48" fill="none"><title>Menu</title><path fill="currentColor" d="M19.528 47.232h40.87c1.952 0 3.515-1.562 3.515-3.564a3.5 3.5 0 0 0-3.516-3.516H19.528a3.501 3.501 0 0 0-3.515 3.516c0 2.002 1.562 3.564 3.515 3.564ZM12.057 27.262h55.81a3.501 3.501 0 0 0 3.516-3.516 3.501 3.501 0 0 0-3.515-3.515h-55.81a3.501 3.501 0 0 0-3.516 3.515 3.501 3.501 0 0 0 3.515 3.516ZM4.391 7.34H75.29c2.002 0 3.515-1.563 3.515-3.516 0-2.002-1.513-3.564-3.515-3.564H4.39C2.438.26.876 1.822.876 3.824A3.501 3.501 0 0 0 4.39 7.34Z"></path></svg></div><div class="vocs_MobileTopNav_menuTitle">Feeds</div></button></div></div><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_5aj_" data-state="closed" class="vocs_MobileTopNav_outlineTrigger">On this page<div aria-label="On this page" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Right</title><path d="M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div></div><div class="vocs_DocsLayout_gutterRight vocs_DocsLayout_gutterRight_withSidebar"><aside class="vocs_Outline"><div class="vocs_AiCtaDropdown"><a class="vocs_Button_button vocs_AiCtaDropdown_buttonLeft vocs_AiCtaDropdown_button vocs_Button_button" href="https://chatgpt.com?hints=search&q=" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><div style="width:14px;height:14px"><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24"><title>OpenAI</title><path fill="currentColor" d="M22.282 9.821a6 6 0 0 0-.516-4.91a6.05 6.05 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a6 6 0 0 0-3.998 2.9a6.05 6.05 0 0 0 .743 7.097a5.98 5.98 0 0 0 .51 4.911a6.05 6.05 0 0 0 6.515 2.9A6 6 0 0 0 13.26 24a6.06 6.06 0 0 0 5.772-4.206a6 6 0 0 0 3.997-2.9a6.06 6.06 0 0 0-.747-7.073M13.26 22.43a4.48 4.48 0 0 1-2.876-1.04l.141-.081l4.779-2.758a.8.8 0 0 0 .392-.681v-6.737l2.02 1.168a.07.07 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494M3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085l4.783 2.759a.77.77 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646M2.34 7.896a4.5 4.5 0 0 1 2.366-1.973V11.6a.77.77 0 0 0 .388.677l5.815 3.354l-2.02 1.168a.08.08 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855l-5.833-3.387L15.119 7.2a.08.08 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667m2.01-3.023l-.141-.085l-4.774-2.782a.78.78 0 0 0-.785 0L9.409 9.23V6.897a.07.07 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135l-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08L8.704 5.46a.8.8 0 0 0-.393.681zm1.097-2.365l2.602-1.5l2.607 1.5v2.999l-2.597 1.5l-2.607-1.5Z"></path></svg></div>Ask in ChatGPT</a><button class="vocs_Button_button vocs_AiCtaDropdown_buttonRight vocs_AiCtaDropdown_button vocs_Button_button" type="button" id="radix-_R_9n_" aria-haspopup="menu" aria-expanded="false" data-state="closed"><div style="width:14px;height:14px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></aside></div><div id="vocs-content" class="vocs_DocsLayout_content vocs_DocsLayout_content_withSidebar vocs_DocsLayout_content_withTopNav"><article class="vocs_Content"><header class="vocs_Header"><h1 class="vocs_H1 vocs_Heading"><div id="feeds" class="vocs_Heading_slugTarget"></div>Feeds<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#feeds" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h1></header> |
|
| 13 | + | <p class="vocs_Paragraph">Minimal RSS Feeds</p> |
|
| 14 | + | <h2 class="vocs_H2 vocs_Heading"><div id="overview" class="vocs_Heading_slugTarget"></div>Overview<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#overview" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 15 | + | <p class="vocs_Paragraph">Feeds is a minimal RSS reader that mimics the original experience of RSS. It's just a list of posts. No categories, no marking a post read or unread, and there is no in-app reading. With this approach you have to read the post on the author's personal website and experience it in its original context.</p> |
|
| 16 | + | <ul class="vocs_List vocs_List_unordered"> |
|
| 17 | + | <li class="vocs_ListItem">Single Rust binary with embedded assets</li> |
|
| 18 | + | <li class="vocs_ListItem">Multiple feed sources: URL params, OPML file, or FreshRSS API</li> |
|
| 19 | + | <li class="vocs_ListItem">Password-protected admin panel for managing subscriptions</li> |
|
| 20 | + | <li class="vocs_ListItem">Feeds API with JSON and OPML export</li> |
|
| 21 | + | <li class="vocs_ListItem">Dark themed UI with Commit Mono font</li> |
|
| 22 | + | </ul> |
|
| 23 | + | <h2 class="vocs_H2 vocs_Heading"><div id="quickstart" class="vocs_Heading_slugTarget"></div>Quickstart<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#quickstart" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 24 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">git</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> clone</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> https://github.com/stevedylandev/andromeda.git</span></span> |
|
| 25 | + | <span class="line vocs_Span"><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span">cd</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> andromeda</span></span> |
|
| 26 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> run</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> feeds</span></span> |
|
| 27 | + | <span class="line vocs_Span"><span style="color:#BDC4CC;--shiki-dark:#BDC4CC" class="vocs_Span"># Server running on http://localhost:3000</span></span></code></pre></div></div> |
|
| 28 | + | <h3 class="vocs_H3 vocs_Heading"><div id="environment-variables" class="vocs_Heading_slugTarget"></div>Environment Variables<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#environment-variables" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 29 | + | <table class="vocs_Table"><thead><tr class="vocs_TableRow"><th class="vocs_TableHeader">Variable</th><th class="vocs_TableHeader">Description</th><th class="vocs_TableHeader">Default</th></tr></thead><tbody><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">FRESHRSS_URL</code></td><td class="vocs_TableCell">URL of your FreshRSS instance</td><td class="vocs_TableCell">--</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">FRESHRSS_USERNAME</code></td><td class="vocs_TableCell">FreshRSS username</td><td class="vocs_TableCell">--</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">FRESHRSS_PASSWORD</code></td><td class="vocs_TableCell">FreshRSS password</td><td class="vocs_TableCell">--</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">ADMIN_PASSWORD</code></td><td class="vocs_TableCell">Password for the admin panel</td><td class="vocs_TableCell">--</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">COOKIE_SECURE</code></td><td class="vocs_TableCell">Enable HTTPS-only cookies</td><td class="vocs_TableCell"><code class="vocs_Code">false</code></td></tr></tbody></table> |
|
| 30 | + | <h2 class="vocs_H2 vocs_Heading"><div id="usage" class="vocs_Heading_slugTarget"></div>Usage<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#usage" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 31 | + | <p class="vocs_Paragraph">There are several built-in ways to source RSS feeds.</p> |
|
| 32 | + | <h3 class="vocs_H3 vocs_Heading"><div id="url-query-param" class="vocs_Heading_slugTarget"></div>URL Query Param<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#url-query-param" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 33 | + | <p class="vocs_Paragraph">Once you have the app running you can add the following to the URL to source an RSS feed:</p> |
|
| 34 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">?url=https://bearblog.dev/discover/feed/</span></span></code></pre></div></div> |
|
| 35 | + | <p class="vocs_Paragraph">You can also add multiple URLs by using commas to separate them:</p> |
|
| 36 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">?urls=https://bearblog.dev/discover/feed/,https://bearblog.stevedylan.dev/feed/</span></span></code></pre></div></div> |
|
| 37 | + | <h3 class="vocs_H3 vocs_Heading"><div id="opml-file" class="vocs_Heading_slugTarget"></div>OPML File<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#opml-file" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 38 | + | <p class="vocs_Paragraph">If you save a <code class="vocs_Code">feeds.opml</code> file in the root of the project the app will automatically source it and fetch the posts for the feeds inside.</p> |
|
| 39 | + | <h3 class="vocs_H3 vocs_Heading"><div id="freshrss-api" class="vocs_Heading_slugTarget"></div>FreshRSS API<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#freshrss-api" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 40 | + | <p class="vocs_Paragraph">If neither of the above are provided the app will default to using a FreshRSS API instance. Set the following environment variables:</p> |
|
| 41 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">FRESHRSS_URL=</span></span> |
|
| 42 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">FRESHRSS_USERNAME=</span></span> |
|
| 43 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">FRESHRSS_PASSWORD=</span></span></code></pre></div></div> |
|
| 44 | + | <h3 class="vocs_H3 vocs_Heading"><div id="admin-panel" class="vocs_Heading_slugTarget"></div>Admin Panel<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#admin-panel" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 45 | + | <p class="vocs_Paragraph">Feeds includes a password-protected admin panel at <code class="vocs_Code">/admin</code> for managing your FreshRSS subscriptions. Set the <code class="vocs_Code">ADMIN_PASSWORD</code> environment variable to enable it. From the admin panel you can view your current subscriptions and add new feeds directly to your FreshRSS instance.</p> |
|
| 46 | + | <h3 class="vocs_H3 vocs_Heading"><div id="feeds-api" class="vocs_Heading_slugTarget"></div>Feeds API<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#feeds-api" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 47 | + | <p class="vocs_Paragraph">The <code class="vocs_Code">/feeds</code> endpoint exports your FreshRSS subscriptions in JSON or OPML format:</p> |
|
| 48 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">/feeds?format=json</span></span> |
|
| 49 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">/feeds?format=opml</span></span></code></pre></div></div> |
|
| 50 | + | <h2 class="vocs_H2 vocs_Heading"><div id="structure" class="vocs_Heading_slugTarget"></div>Structure<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#structure" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 51 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">feeds/</span></span> |
|
| 52 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── src/</span></span> |
|
| 53 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── main.rs # Axum server with routing, templates, and static asset serving</span></span> |
|
| 54 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── feeds.rs # Feed fetching, OPML parsing, and FreshRSS API integration</span></span> |
|
| 55 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── auth.rs # Session-based authentication with constant-time password verification</span></span> |
|
| 56 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ └── models.rs # Data structures for feeds and FreshRSS responses</span></span> |
|
| 57 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── templates/ # Askama HTML templates</span></span> |
|
| 58 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── assets/ # Static assets embedded at compile time via rust-embed</span></span> |
|
| 59 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── Dockerfile</span></span> |
|
| 60 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">└── docker-compose.yml</span></span></code></pre></div></div> |
|
| 61 | + | <h2 class="vocs_H2 vocs_Heading"><div id="deployment" class="vocs_Heading_slugTarget"></div>Deployment<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#deployment" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 62 | + | <h3 class="vocs_H3 vocs_Heading"><div id="railway" class="vocs_Heading_slugTarget"></div>Railway<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#railway" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 63 | + | <p class="vocs_Paragraph"><a class="vocs_Anchor" href="https://railway.com/deploy/Ezvmhx?referralCode=JGcIp6" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><img src="https://railway.com/button.svg" alt="Deploy on Railway"/></a></p> |
|
| 64 | + | <h3 class="vocs_H3 vocs_Heading"><div id="docker" class="vocs_Heading_slugTarget"></div>Docker<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#docker" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 65 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span">cd</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> apps/feeds</span></span> |
|
| 66 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cp</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> .env.sample</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> .env</span></span> |
|
| 67 | + | <span class="line vocs_Span"><span style="color:#BDC4CC;--shiki-dark:#BDC4CC" class="vocs_Span"># Edit .env with your credentials</span></span> |
|
| 68 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">docker</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> compose</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> up</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -d</span></span></code></pre></div></div> |
|
| 69 | + | <h3 class="vocs_H3 vocs_Heading"><div id="binary" class="vocs_Heading_slugTarget"></div>Binary<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/feeds#binary" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 70 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> build</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> --release</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> feeds</span></span></code></pre></div></div> |
|
| 71 | + | <p class="vocs_Paragraph">The resulting binary is self-contained with all assets embedded. Copy it to your server with a configured <code class="vocs_Code">.env</code> file and run it directly.</p></article><footer class="vocs_Footer" data-layout="docs"><div class="vocs_Footer_container"></div></footer></div><div data-bottom-observer="true"></div></div></div> |
|
| 72 | + | </body> |
|
| 73 | + | </html> |
| 1 | + | <!doctype html> |
|
| 2 | + | <html lang="en" class="dark" data-vocs> |
|
| 3 | + | <head> |
|
| 4 | + | <meta charset="UTF-8" /> |
|
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
| 6 | + | <script src="/initializeTheme.iife.js"></script><link rel="preload" as="image" href="https://railway.com/button.svg"/><title>Jotts – Andromeda</title><meta property="og:type" content="website"/><meta property="og:title" content="Jotts"/><meta name="twitter:card" content="summary_large_image"/> |
|
| 7 | + | <script type="module" crossorigin src="/assets/index-DO6OtFZH.js"></script> |
|
| 8 | + | <link rel="stylesheet" crossorigin href="/assets/style-Dg8GuVX0.css"> |
|
| 9 | + | </head> |
|
| 10 | + | <body> |
|
| 11 | + | <span style="display: none;">Are you an LLM? Read <a href="/llms.txt">llms.txt</a> for a summary of the docs, or <a href="/llms-full.txt">llms-full.txt</a> for the full context.</span> |
|
| 12 | + | <div id="app"><div class="vocs_DocsLayout" data-layout="docs"><a class="vocs_SkipLink vocs_utils_visuallyHidden" href="/apps/jotts#vocs-content">Skip to content</a><div class="vocs_DocsLayout_gutterLeft"><aside class="vocs_Sidebar vocs_DocsLayout_sidebar"><div><div class="vocs_Sidebar_logoWrapper"><div class="vocs_Sidebar_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div><div class="vocs_Sidebar_divider"></div></div><nav class="vocs_Sidebar_navigation"><div class="vocs_Sidebar_group"><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Intro</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/quickstart" data-discover="true">Quickstart</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/what-is-andromeda" data-discover="true">What is Andromeda</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Apps</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/feeds" data-discover="true">Feeds</a><a data-active="true" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/jotts" data-discover="true">Jotts</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/sipp" data-discover="true">Sipp</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/og" data-discover="true">OG</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/shrink" data-discover="true">Shrink</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/parcels" data-discover="true">Parcels</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">DIY</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/stack" data-discover="true">Stack</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/skills" data-discover="true">Skills</a></div></section></div></nav></div><div class="vocs_Sidebar_footer"><div class="vocs_Sidebar_footerCurtain"></div><div class="vocs_Sidebar_footerContent"></div></div></aside></div><div class="vocs_DocsLayout_gutterTop vocs_DocsLayout_gutterTop_offsetLeftGutter"><div class="vocs_DesktopTopNav"><button class="vocs_DesktopSearch_search" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_4lj_" data-state="closed"><svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-top:2px"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>Search...<div class="vocs_DesktopSearch_searchCommand"><div style="background:currentColor;transform:rotate(45deg);width:1.5px;border-radius:2px;height:100%"></div></div></button><div class="vocs_DesktopTopNav_logoWrapper"><div class="vocs_DesktopTopNav_logo"><a style="align-items:center;display:flex;height:56px;margin-top:4px" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_DesktopTopNav_section"></div><div class="vocs_DesktopTopNav_section"></div></div><div class="vocs_MobileTopNav"><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group"><div class="vocs_MobileTopNav_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_MobileTopNav_group"><nav aria-label="Main" data-orientation="horizontal" dir="ltr" class="vocs_MobileTopNav_navigation vocs_NavigationMenu"><div style="position:relative"><ul data-orientation="horizontal" class="vocs_NavigationMenu_list" dir="ltr"></ul></div></nav><div class="vocs_MobileTopNav_navigation vocs_MobileTopNav_navigation_compact"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_kpj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger vocs_MobileTopNav_navigationItem">Menu<div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group" style="margin-right:-8px"><button class="vocs_MobileSearch_searchButton" type="button" aria-label="Search" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_39j_" data-state="closed"><svg width="21" height="21" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div></div></div></div><div class="vocs_DocsLayout_gutterTopCurtain vocs_DocsLayout_gutterTopCurtain_withSidebar"><div class="vocs_DesktopTopNav_curtain"></div><div class="vocs_MobileTopNav_curtain"><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_qj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger"><div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:13px"><svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 79 48" fill="none"><title>Menu</title><path fill="currentColor" d="M19.528 47.232h40.87c1.952 0 3.515-1.562 3.515-3.564a3.5 3.5 0 0 0-3.516-3.516H19.528a3.501 3.501 0 0 0-3.515 3.516c0 2.002 1.562 3.564 3.515 3.564ZM12.057 27.262h55.81a3.501 3.501 0 0 0 3.516-3.516 3.501 3.501 0 0 0-3.515-3.515h-55.81a3.501 3.501 0 0 0-3.516 3.515 3.501 3.501 0 0 0 3.515 3.516ZM4.391 7.34H75.29c2.002 0 3.515-1.563 3.515-3.516 0-2.002-1.513-3.564-3.515-3.564H4.39C2.438.26.876 1.822.876 3.824A3.501 3.501 0 0 0 4.39 7.34Z"></path></svg></div><div class="vocs_MobileTopNav_menuTitle">Jotts</div></button></div></div><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_5aj_" data-state="closed" class="vocs_MobileTopNav_outlineTrigger">On this page<div aria-label="On this page" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Right</title><path d="M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div></div><div class="vocs_DocsLayout_gutterRight vocs_DocsLayout_gutterRight_withSidebar"><aside class="vocs_Outline"><div class="vocs_AiCtaDropdown"><a class="vocs_Button_button vocs_AiCtaDropdown_buttonLeft vocs_AiCtaDropdown_button vocs_Button_button" href="https://chatgpt.com?hints=search&q=" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><div style="width:14px;height:14px"><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24"><title>OpenAI</title><path fill="currentColor" d="M22.282 9.821a6 6 0 0 0-.516-4.91a6.05 6.05 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a6 6 0 0 0-3.998 2.9a6.05 6.05 0 0 0 .743 7.097a5.98 5.98 0 0 0 .51 4.911a6.05 6.05 0 0 0 6.515 2.9A6 6 0 0 0 13.26 24a6.06 6.06 0 0 0 5.772-4.206a6 6 0 0 0 3.997-2.9a6.06 6.06 0 0 0-.747-7.073M13.26 22.43a4.48 4.48 0 0 1-2.876-1.04l.141-.081l4.779-2.758a.8.8 0 0 0 .392-.681v-6.737l2.02 1.168a.07.07 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494M3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085l4.783 2.759a.77.77 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646M2.34 7.896a4.5 4.5 0 0 1 2.366-1.973V11.6a.77.77 0 0 0 .388.677l5.815 3.354l-2.02 1.168a.08.08 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855l-5.833-3.387L15.119 7.2a.08.08 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667m2.01-3.023l-.141-.085l-4.774-2.782a.78.78 0 0 0-.785 0L9.409 9.23V6.897a.07.07 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135l-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08L8.704 5.46a.8.8 0 0 0-.393.681zm1.097-2.365l2.602-1.5l2.607 1.5v2.999l-2.597 1.5l-2.607-1.5Z"></path></svg></div>Ask in ChatGPT</a><button class="vocs_Button_button vocs_AiCtaDropdown_buttonRight vocs_AiCtaDropdown_button vocs_Button_button" type="button" id="radix-_R_9n_" aria-haspopup="menu" aria-expanded="false" data-state="closed"><div style="width:14px;height:14px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></aside></div><div id="vocs-content" class="vocs_DocsLayout_content vocs_DocsLayout_content_withSidebar vocs_DocsLayout_content_withTopNav"><article class="vocs_Content"><header class="vocs_Header"><h1 class="vocs_H1 vocs_Heading"><div id="jotts" class="vocs_Heading_slugTarget"></div>Jotts<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/jotts#jotts" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h1></header> |
|
| 13 | + | <p class="vocs_Paragraph">A minimal notes app</p> |
|
| 14 | + | <h2 class="vocs_H2 vocs_Heading"><div id="overview" class="vocs_Heading_slugTarget"></div>Overview<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/jotts#overview" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 15 | + | <p class="vocs_Paragraph">A simple, self-hosted markdown note app built with Rust.</p> |
|
| 16 | + | <ul class="vocs_List vocs_List_unordered"> |
|
| 17 | + | <li class="vocs_ListItem">Single ~7MB Rust binary with embedded assets</li> |
|
| 18 | + | <li class="vocs_ListItem">Password authentication with session cookies</li> |
|
| 19 | + | <li class="vocs_ListItem">Create, edit, and delete markdown notes</li> |
|
| 20 | + | <li class="vocs_ListItem">Markdown rendering with strikethrough, tables, and task lists</li> |
|
| 21 | + | <li class="vocs_ListItem">Dark themed UI with Commit Mono font</li> |
|
| 22 | + | <li class="vocs_ListItem">SQLite for persistent storage</li> |
|
| 23 | + | </ul> |
|
| 24 | + | <h2 class="vocs_H2 vocs_Heading"><div id="quickstart" class="vocs_Heading_slugTarget"></div>Quickstart<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/jotts#quickstart" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 25 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">git</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> clone</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> https://github.com/stevedylandev/andromeda.git</span></span> |
|
| 26 | + | <span class="line vocs_Span"><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span">cd</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> andromeda</span></span> |
|
| 27 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cp</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> apps/jotts/.env.example</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> .env</span></span> |
|
| 28 | + | <span class="line vocs_Span"><span style="color:#BDC4CC;--shiki-dark:#BDC4CC" class="vocs_Span"># Edit .env with your password</span></span> |
|
| 29 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> run</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> jotts</span></span></code></pre></div></div> |
|
| 30 | + | <h3 class="vocs_H3 vocs_Heading"><div id="environment-variables" class="vocs_Heading_slugTarget"></div>Environment Variables<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/jotts#environment-variables" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 31 | + | <table class="vocs_Table"><thead><tr class="vocs_TableRow"><th class="vocs_TableHeader">Variable</th><th class="vocs_TableHeader">Description</th><th class="vocs_TableHeader">Default</th></tr></thead><tbody><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">JOTTS_PASSWORD</code></td><td class="vocs_TableCell">Password for login authentication</td><td class="vocs_TableCell"><code class="vocs_Code">changeme</code></td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">JOTTS_DB_PATH</code></td><td class="vocs_TableCell">SQLite database file path</td><td class="vocs_TableCell"><code class="vocs_Code">jotts.sqlite</code></td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">HOST</code></td><td class="vocs_TableCell">Server bind address</td><td class="vocs_TableCell"><code class="vocs_Code">127.0.0.1</code></td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">PORT</code></td><td class="vocs_TableCell">Server port</td><td class="vocs_TableCell"><code class="vocs_Code">3000</code></td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">COOKIE_SECURE</code></td><td class="vocs_TableCell">Enable HTTPS-only cookies</td><td class="vocs_TableCell"><code class="vocs_Code">false</code></td></tr></tbody></table> |
|
| 32 | + | <h2 class="vocs_H2 vocs_Heading"><div id="structure" class="vocs_Heading_slugTarget"></div>Structure<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/jotts#structure" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 33 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">jotts/</span></span> |
|
| 34 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── src/</span></span> |
|
| 35 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── main.rs # App entrypoint, env vars, starts server</span></span> |
|
| 36 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── server.rs # Axum router, HTTP handlers, and templates</span></span> |
|
| 37 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── auth.rs # Password verification and session management</span></span> |
|
| 38 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ └── db.rs # SQLite database layer (notes, sessions)</span></span> |
|
| 39 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── templates/ # Askama HTML templates</span></span> |
|
| 40 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── base.html # Base layout with header and nav</span></span> |
|
| 41 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── login.html # Login page</span></span> |
|
| 42 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── index.html # Note list</span></span> |
|
| 43 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── view.html # Single note display</span></span> |
|
| 44 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── new.html # Create note form</span></span> |
|
| 45 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ └── edit.html # Edit note form</span></span> |
|
| 46 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── static/ # Favicons, og:image, styles, and webmanifest</span></span> |
|
| 47 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── assets/ # Commit Mono font files</span></span> |
|
| 48 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── Dockerfile</span></span> |
|
| 49 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">└── docker-compose.yml</span></span></code></pre></div></div> |
|
| 50 | + | <h2 class="vocs_H2 vocs_Heading"><div id="deployment" class="vocs_Heading_slugTarget"></div>Deployment<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/jotts#deployment" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 51 | + | <h3 class="vocs_H3 vocs_Heading"><div id="railway" class="vocs_Heading_slugTarget"></div>Railway<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/jotts#railway" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 52 | + | <p class="vocs_Paragraph"><a class="vocs_Anchor" href="https://railway.com/deploy/DLhUhH?referralCode=JGcIp6" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><img src="https://railway.com/button.svg" alt="Deploy on Railway"/></a></p> |
|
| 53 | + | <h3 class="vocs_H3 vocs_Heading"><div id="docker" class="vocs_Heading_slugTarget"></div>Docker<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/jotts#docker" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 54 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span">cd</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> apps/jotts</span></span> |
|
| 55 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cp</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> .env.example</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> .env</span></span> |
|
| 56 | + | <span class="line vocs_Span"><span style="color:#BDC4CC;--shiki-dark:#BDC4CC" class="vocs_Span"># Edit .env with your password</span></span> |
|
| 57 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">docker</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> compose</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> up</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -d</span></span></code></pre></div></div> |
|
| 58 | + | <p class="vocs_Paragraph">This will start Jotts on port <code class="vocs_Code">3000</code> with a persistent volume for the SQLite database.</p> |
|
| 59 | + | <h3 class="vocs_H3 vocs_Heading"><div id="binary" class="vocs_Heading_slugTarget"></div>Binary<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/jotts#binary" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 60 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> build</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> --release</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> jotts</span></span></code></pre></div></div> |
|
| 61 | + | <p class="vocs_Paragraph">The resulting binary is self-contained with all assets embedded. Copy it to your server with a configured <code class="vocs_Code">.env</code> file and run it directly.</p></article><footer class="vocs_Footer" data-layout="docs"><div class="vocs_Footer_container"></div></footer></div><div data-bottom-observer="true"></div></div></div> |
|
| 62 | + | </body> |
|
| 63 | + | </html> |
| 1 | + | <!doctype html> |
|
| 2 | + | <html lang="en" class="dark" data-vocs> |
|
| 3 | + | <head> |
|
| 4 | + | <meta charset="UTF-8" /> |
|
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
| 6 | + | <script src="/initializeTheme.iife.js"></script><link rel="preload" as="image" href="https://railway.com/button.svg"/><title>OG – Andromeda</title><meta property="og:type" content="website"/><meta property="og:title" content="OG"/><meta name="twitter:card" content="summary_large_image"/> |
|
| 7 | + | <script type="module" crossorigin src="/assets/index-DO6OtFZH.js"></script> |
|
| 8 | + | <link rel="stylesheet" crossorigin href="/assets/style-Dg8GuVX0.css"> |
|
| 9 | + | </head> |
|
| 10 | + | <body> |
|
| 11 | + | <span style="display: none;">Are you an LLM? Read <a href="/llms.txt">llms.txt</a> for a summary of the docs, or <a href="/llms-full.txt">llms-full.txt</a> for the full context.</span> |
|
| 12 | + | <div id="app"><div class="vocs_DocsLayout" data-layout="docs"><a class="vocs_SkipLink vocs_utils_visuallyHidden" href="/apps/og#vocs-content">Skip to content</a><div class="vocs_DocsLayout_gutterLeft"><aside class="vocs_Sidebar vocs_DocsLayout_sidebar"><div><div class="vocs_Sidebar_logoWrapper"><div class="vocs_Sidebar_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div><div class="vocs_Sidebar_divider"></div></div><nav class="vocs_Sidebar_navigation"><div class="vocs_Sidebar_group"><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Intro</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/quickstart" data-discover="true">Quickstart</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/what-is-andromeda" data-discover="true">What is Andromeda</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Apps</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/feeds" data-discover="true">Feeds</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/jotts" data-discover="true">Jotts</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/sipp" data-discover="true">Sipp</a><a data-active="true" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/og" data-discover="true">OG</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/shrink" data-discover="true">Shrink</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/parcels" data-discover="true">Parcels</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">DIY</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/stack" data-discover="true">Stack</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/skills" data-discover="true">Skills</a></div></section></div></nav></div><div class="vocs_Sidebar_footer"><div class="vocs_Sidebar_footerCurtain"></div><div class="vocs_Sidebar_footerContent"></div></div></aside></div><div class="vocs_DocsLayout_gutterTop vocs_DocsLayout_gutterTop_offsetLeftGutter"><div class="vocs_DesktopTopNav"><button class="vocs_DesktopSearch_search" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_4lj_" data-state="closed"><svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-top:2px"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>Search...<div class="vocs_DesktopSearch_searchCommand"><div style="background:currentColor;transform:rotate(45deg);width:1.5px;border-radius:2px;height:100%"></div></div></button><div class="vocs_DesktopTopNav_logoWrapper"><div class="vocs_DesktopTopNav_logo"><a style="align-items:center;display:flex;height:56px;margin-top:4px" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_DesktopTopNav_section"></div><div class="vocs_DesktopTopNav_section"></div></div><div class="vocs_MobileTopNav"><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group"><div class="vocs_MobileTopNav_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_MobileTopNav_group"><nav aria-label="Main" data-orientation="horizontal" dir="ltr" class="vocs_MobileTopNav_navigation vocs_NavigationMenu"><div style="position:relative"><ul data-orientation="horizontal" class="vocs_NavigationMenu_list" dir="ltr"></ul></div></nav><div class="vocs_MobileTopNav_navigation vocs_MobileTopNav_navigation_compact"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_kpj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger vocs_MobileTopNav_navigationItem">Menu<div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group" style="margin-right:-8px"><button class="vocs_MobileSearch_searchButton" type="button" aria-label="Search" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_39j_" data-state="closed"><svg width="21" height="21" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div></div></div></div><div class="vocs_DocsLayout_gutterTopCurtain vocs_DocsLayout_gutterTopCurtain_withSidebar"><div class="vocs_DesktopTopNav_curtain"></div><div class="vocs_MobileTopNav_curtain"><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_qj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger"><div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:13px"><svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 79 48" fill="none"><title>Menu</title><path fill="currentColor" d="M19.528 47.232h40.87c1.952 0 3.515-1.562 3.515-3.564a3.5 3.5 0 0 0-3.516-3.516H19.528a3.501 3.501 0 0 0-3.515 3.516c0 2.002 1.562 3.564 3.515 3.564ZM12.057 27.262h55.81a3.501 3.501 0 0 0 3.516-3.516 3.501 3.501 0 0 0-3.515-3.515h-55.81a3.501 3.501 0 0 0-3.516 3.515 3.501 3.501 0 0 0 3.515 3.516ZM4.391 7.34H75.29c2.002 0 3.515-1.563 3.515-3.516 0-2.002-1.513-3.564-3.515-3.564H4.39C2.438.26.876 1.822.876 3.824A3.501 3.501 0 0 0 4.39 7.34Z"></path></svg></div><div class="vocs_MobileTopNav_menuTitle">OG</div></button></div></div><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_5aj_" data-state="closed" class="vocs_MobileTopNav_outlineTrigger">On this page<div aria-label="On this page" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Right</title><path d="M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div></div><div class="vocs_DocsLayout_gutterRight vocs_DocsLayout_gutterRight_withSidebar"><aside class="vocs_Outline"><div class="vocs_AiCtaDropdown"><a class="vocs_Button_button vocs_AiCtaDropdown_buttonLeft vocs_AiCtaDropdown_button vocs_Button_button" href="https://chatgpt.com?hints=search&q=" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><div style="width:14px;height:14px"><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24"><title>OpenAI</title><path fill="currentColor" d="M22.282 9.821a6 6 0 0 0-.516-4.91a6.05 6.05 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a6 6 0 0 0-3.998 2.9a6.05 6.05 0 0 0 .743 7.097a5.98 5.98 0 0 0 .51 4.911a6.05 6.05 0 0 0 6.515 2.9A6 6 0 0 0 13.26 24a6.06 6.06 0 0 0 5.772-4.206a6 6 0 0 0 3.997-2.9a6.06 6.06 0 0 0-.747-7.073M13.26 22.43a4.48 4.48 0 0 1-2.876-1.04l.141-.081l4.779-2.758a.8.8 0 0 0 .392-.681v-6.737l2.02 1.168a.07.07 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494M3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085l4.783 2.759a.77.77 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646M2.34 7.896a4.5 4.5 0 0 1 2.366-1.973V11.6a.77.77 0 0 0 .388.677l5.815 3.354l-2.02 1.168a.08.08 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855l-5.833-3.387L15.119 7.2a.08.08 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667m2.01-3.023l-.141-.085l-4.774-2.782a.78.78 0 0 0-.785 0L9.409 9.23V6.897a.07.07 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135l-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08L8.704 5.46a.8.8 0 0 0-.393.681zm1.097-2.365l2.602-1.5l2.607 1.5v2.999l-2.597 1.5l-2.607-1.5Z"></path></svg></div>Ask in ChatGPT</a><button class="vocs_Button_button vocs_AiCtaDropdown_buttonRight vocs_AiCtaDropdown_button vocs_Button_button" type="button" id="radix-_R_9n_" aria-haspopup="menu" aria-expanded="false" data-state="closed"><div style="width:14px;height:14px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></aside></div><div id="vocs-content" class="vocs_DocsLayout_content vocs_DocsLayout_content_withSidebar vocs_DocsLayout_content_withTopNav"><article class="vocs_Content"><header class="vocs_Header"><h1 class="vocs_H1 vocs_Heading"><div id="og" class="vocs_Heading_slugTarget"></div>OG<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/og#og" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h1></header> |
|
| 13 | + | <p class="vocs_Paragraph">A simple web tool for inspecting Open Graph tags on any URL.</p> |
|
| 14 | + | <h2 class="vocs_H2 vocs_Heading"><div id="overview" class="vocs_Heading_slugTarget"></div>Overview<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/og#overview" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 15 | + | <p class="vocs_Paragraph">A self-hosted Open Graph tag inspector built with Rust. Enter any URL and instantly see its OG metadata.</p> |
|
| 16 | + | <ul class="vocs_List vocs_List_unordered"> |
|
| 17 | + | <li class="vocs_ListItem">Single Rust binary with embedded assets</li> |
|
| 18 | + | <li class="vocs_ListItem">Inspects title, description, image, and other OG tags</li> |
|
| 19 | + | <li class="vocs_ListItem">Dark themed UI with Commit Mono font</li> |
|
| 20 | + | <li class="vocs_ListItem">No database needed -- fully stateless</li> |
|
| 21 | + | </ul> |
|
| 22 | + | <h2 class="vocs_H2 vocs_Heading"><div id="quickstart" class="vocs_Heading_slugTarget"></div>Quickstart<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/og#quickstart" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 23 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">git</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> clone</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> https://github.com/stevedylandev/andromeda.git</span></span> |
|
| 24 | + | <span class="line vocs_Span"><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span">cd</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> andromeda</span></span> |
|
| 25 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> run</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> og</span></span></code></pre></div></div> |
|
| 26 | + | <h3 class="vocs_H3 vocs_Heading"><div id="environment-variables" class="vocs_Heading_slugTarget"></div>Environment Variables<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/og#environment-variables" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 27 | + | <table class="vocs_Table"><thead><tr class="vocs_TableRow"><th class="vocs_TableHeader">Variable</th><th class="vocs_TableHeader">Description</th><th class="vocs_TableHeader">Default</th></tr></thead><tbody><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">PORT</code></td><td class="vocs_TableCell">Server port</td><td class="vocs_TableCell"><code class="vocs_Code">3000</code></td></tr></tbody></table> |
|
| 28 | + | <h2 class="vocs_H2 vocs_Heading"><div id="structure" class="vocs_Heading_slugTarget"></div>Structure<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/og#structure" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 29 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">og/</span></span> |
|
| 30 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── src/</span></span> |
|
| 31 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── main.rs # Entry point and server startup</span></span> |
|
| 32 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── server.rs # Axum routes and request handling</span></span> |
|
| 33 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ └── og.rs # Open Graph tag fetching and parsing</span></span> |
|
| 34 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── templates/ # Askama HTML templates</span></span> |
|
| 35 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── base.html # Base layout</span></span> |
|
| 36 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── index.html # Search form</span></span> |
|
| 37 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ └── results.html # OG tag results display</span></span> |
|
| 38 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── static/ # Fonts, favicons, and styles</span></span> |
|
| 39 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── Dockerfile</span></span> |
|
| 40 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">└── docker-compose.yml</span></span></code></pre></div></div> |
|
| 41 | + | <h2 class="vocs_H2 vocs_Heading"><div id="deployment" class="vocs_Heading_slugTarget"></div>Deployment<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/og#deployment" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 42 | + | <h3 class="vocs_H3 vocs_Heading"><div id="railway" class="vocs_Heading_slugTarget"></div>Railway<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/og#railway" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 43 | + | <p class="vocs_Paragraph"><a class="vocs_Anchor" href="https://railway.com/deploy/OdXBt_?referralCode=JGcIp6" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><img src="https://railway.com/button.svg" alt="Deploy on Railway"/></a></p> |
|
| 44 | + | <h3 class="vocs_H3 vocs_Heading"><div id="docker" class="vocs_Heading_slugTarget"></div>Docker<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/og#docker" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 45 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span">cd</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> apps/og</span></span> |
|
| 46 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">docker</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> compose</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> up</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -d</span></span></code></pre></div></div> |
|
| 47 | + | <h3 class="vocs_H3 vocs_Heading"><div id="binary" class="vocs_Heading_slugTarget"></div>Binary<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/og#binary" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 48 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> build</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> --release</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> og</span></span></code></pre></div></div> |
|
| 49 | + | <p class="vocs_Paragraph">The resulting binary is self-contained with all assets embedded. Copy it to your server and run it directly.</p></article><footer class="vocs_Footer" data-layout="docs"><div class="vocs_Footer_container"></div></footer></div><div data-bottom-observer="true"></div></div></div> |
|
| 50 | + | </body> |
|
| 51 | + | </html> |
| 1 | + | <!doctype html> |
|
| 2 | + | <html lang="en" class="dark" data-vocs> |
|
| 3 | + | <head> |
|
| 4 | + | <meta charset="UTF-8" /> |
|
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
| 6 | + | <script src="/initializeTheme.iife.js"></script><link rel="preload" as="image" href="https://railway.com/button.svg"/><title>Parcels – Andromeda</title><meta property="og:type" content="website"/><meta property="og:title" content="Parcels"/><meta name="twitter:card" content="summary_large_image"/> |
|
| 7 | + | <script type="module" crossorigin src="/assets/index-DO6OtFZH.js"></script> |
|
| 8 | + | <link rel="stylesheet" crossorigin href="/assets/style-Dg8GuVX0.css"> |
|
| 9 | + | </head> |
|
| 10 | + | <body> |
|
| 11 | + | <span style="display: none;">Are you an LLM? Read <a href="/llms.txt">llms.txt</a> for a summary of the docs, or <a href="/llms-full.txt">llms-full.txt</a> for the full context.</span> |
|
| 12 | + | <div id="app"><div class="vocs_DocsLayout" data-layout="docs"><a class="vocs_SkipLink vocs_utils_visuallyHidden" href="/apps/parcels#vocs-content">Skip to content</a><div class="vocs_DocsLayout_gutterLeft"><aside class="vocs_Sidebar vocs_DocsLayout_sidebar"><div><div class="vocs_Sidebar_logoWrapper"><div class="vocs_Sidebar_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div><div class="vocs_Sidebar_divider"></div></div><nav class="vocs_Sidebar_navigation"><div class="vocs_Sidebar_group"><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Intro</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/quickstart" data-discover="true">Quickstart</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/what-is-andromeda" data-discover="true">What is Andromeda</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Apps</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/feeds" data-discover="true">Feeds</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/jotts" data-discover="true">Jotts</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/sipp" data-discover="true">Sipp</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/og" data-discover="true">OG</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/shrink" data-discover="true">Shrink</a><a data-active="true" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/parcels" data-discover="true">Parcels</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">DIY</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/stack" data-discover="true">Stack</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/skills" data-discover="true">Skills</a></div></section></div></nav></div><div class="vocs_Sidebar_footer"><div class="vocs_Sidebar_footerCurtain"></div><div class="vocs_Sidebar_footerContent"></div></div></aside></div><div class="vocs_DocsLayout_gutterTop vocs_DocsLayout_gutterTop_offsetLeftGutter"><div class="vocs_DesktopTopNav"><button class="vocs_DesktopSearch_search" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_4lj_" data-state="closed"><svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-top:2px"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>Search...<div class="vocs_DesktopSearch_searchCommand"><div style="background:currentColor;transform:rotate(45deg);width:1.5px;border-radius:2px;height:100%"></div></div></button><div class="vocs_DesktopTopNav_logoWrapper"><div class="vocs_DesktopTopNav_logo"><a style="align-items:center;display:flex;height:56px;margin-top:4px" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_DesktopTopNav_section"></div><div class="vocs_DesktopTopNav_section"></div></div><div class="vocs_MobileTopNav"><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group"><div class="vocs_MobileTopNav_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_MobileTopNav_group"><nav aria-label="Main" data-orientation="horizontal" dir="ltr" class="vocs_MobileTopNav_navigation vocs_NavigationMenu"><div style="position:relative"><ul data-orientation="horizontal" class="vocs_NavigationMenu_list" dir="ltr"></ul></div></nav><div class="vocs_MobileTopNav_navigation vocs_MobileTopNav_navigation_compact"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_kpj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger vocs_MobileTopNav_navigationItem">Menu<div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group" style="margin-right:-8px"><button class="vocs_MobileSearch_searchButton" type="button" aria-label="Search" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_39j_" data-state="closed"><svg width="21" height="21" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div></div></div></div><div class="vocs_DocsLayout_gutterTopCurtain vocs_DocsLayout_gutterTopCurtain_withSidebar"><div class="vocs_DesktopTopNav_curtain"></div><div class="vocs_MobileTopNav_curtain"><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_qj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger"><div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:13px"><svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 79 48" fill="none"><title>Menu</title><path fill="currentColor" d="M19.528 47.232h40.87c1.952 0 3.515-1.562 3.515-3.564a3.5 3.5 0 0 0-3.516-3.516H19.528a3.501 3.501 0 0 0-3.515 3.516c0 2.002 1.562 3.564 3.515 3.564ZM12.057 27.262h55.81a3.501 3.501 0 0 0 3.516-3.516 3.501 3.501 0 0 0-3.515-3.515h-55.81a3.501 3.501 0 0 0-3.516 3.515 3.501 3.501 0 0 0 3.515 3.516ZM4.391 7.34H75.29c2.002 0 3.515-1.563 3.515-3.516 0-2.002-1.513-3.564-3.515-3.564H4.39C2.438.26.876 1.822.876 3.824A3.501 3.501 0 0 0 4.39 7.34Z"></path></svg></div><div class="vocs_MobileTopNav_menuTitle">Parcels</div></button></div></div><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_5aj_" data-state="closed" class="vocs_MobileTopNav_outlineTrigger">On this page<div aria-label="On this page" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Right</title><path d="M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div></div><div class="vocs_DocsLayout_gutterRight vocs_DocsLayout_gutterRight_withSidebar"><aside class="vocs_Outline"><div class="vocs_AiCtaDropdown"><a class="vocs_Button_button vocs_AiCtaDropdown_buttonLeft vocs_AiCtaDropdown_button vocs_Button_button" href="https://chatgpt.com?hints=search&q=" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><div style="width:14px;height:14px"><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24"><title>OpenAI</title><path fill="currentColor" d="M22.282 9.821a6 6 0 0 0-.516-4.91a6.05 6.05 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a6 6 0 0 0-3.998 2.9a6.05 6.05 0 0 0 .743 7.097a5.98 5.98 0 0 0 .51 4.911a6.05 6.05 0 0 0 6.515 2.9A6 6 0 0 0 13.26 24a6.06 6.06 0 0 0 5.772-4.206a6 6 0 0 0 3.997-2.9a6.06 6.06 0 0 0-.747-7.073M13.26 22.43a4.48 4.48 0 0 1-2.876-1.04l.141-.081l4.779-2.758a.8.8 0 0 0 .392-.681v-6.737l2.02 1.168a.07.07 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494M3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085l4.783 2.759a.77.77 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646M2.34 7.896a4.5 4.5 0 0 1 2.366-1.973V11.6a.77.77 0 0 0 .388.677l5.815 3.354l-2.02 1.168a.08.08 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855l-5.833-3.387L15.119 7.2a.08.08 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667m2.01-3.023l-.141-.085l-4.774-2.782a.78.78 0 0 0-.785 0L9.409 9.23V6.897a.07.07 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135l-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08L8.704 5.46a.8.8 0 0 0-.393.681zm1.097-2.365l2.602-1.5l2.607 1.5v2.999l-2.597 1.5l-2.607-1.5Z"></path></svg></div>Ask in ChatGPT</a><button class="vocs_Button_button vocs_AiCtaDropdown_buttonRight vocs_AiCtaDropdown_button vocs_Button_button" type="button" id="radix-_R_9n_" aria-haspopup="menu" aria-expanded="false" data-state="closed"><div style="width:14px;height:14px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></aside></div><div id="vocs-content" class="vocs_DocsLayout_content vocs_DocsLayout_content_withSidebar vocs_DocsLayout_content_withTopNav"><article class="vocs_Content"><header class="vocs_Header"><h1 class="vocs_H1 vocs_Heading"><div id="parcels" class="vocs_Heading_slugTarget"></div>Parcels<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/parcels#parcels" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h1></header> |
|
| 13 | + | <p class="vocs_Paragraph">A minimal package tracking app</p> |
|
| 14 | + | <aside class="vocs_Aside vocs_Callout vocs_Callout_warning"><div class="vocs_Callout_icon"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Exclamation</title><path d="M8.4449 0.608765C8.0183 -0.107015 6.9817 -0.107015 6.55509 0.608766L0.161178 11.3368C-0.275824 12.07 0.252503 13 1.10608 13H13.8939C14.7475 13 15.2758 12.07 14.8388 11.3368L8.4449 0.608765ZM7.4141 1.12073C7.45288 1.05566 7.54712 1.05566 7.5859 1.12073L13.9798 11.8488C14.0196 11.9154 13.9715 12 13.8939 12H1.10608C1.02849 12 0.980454 11.9154 1.02018 11.8488L7.4141 1.12073ZM6.8269 4.48611C6.81221 4.10423 7.11783 3.78663 7.5 3.78663C7.88217 3.78663 8.18778 4.10423 8.1731 4.48612L8.01921 8.48701C8.00848 8.766 7.7792 8.98664 7.5 8.98664C7.2208 8.98664 6.99151 8.766 6.98078 8.48701L6.8269 4.48611ZM8.24989 10.476C8.24989 10.8902 7.9141 11.226 7.49989 11.226C7.08567 11.226 6.74989 10.8902 6.74989 10.476C6.74989 10.0618 7.08567 9.72599 7.49989 9.72599C7.9141 9.72599 8.24989 10.0618 8.24989 10.476Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div><div class="vocs_Callout_content"><p class="vocs_Paragraph">This app originally used USPS, but starting April 1st 2026, it has become much harder to obtain/maintain API keys.</p></div></aside> |
|
| 15 | + | <h2 class="vocs_H2 vocs_Heading"><div id="overview" class="vocs_Heading_slugTarget"></div>Overview<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/parcels#overview" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 16 | + | <p class="vocs_Paragraph">A self-hosted package tracker for USPS. Track your packages without logging into USPS every time.</p> |
|
| 17 | + | <ul class="vocs_List vocs_List_unordered"> |
|
| 18 | + | <li class="vocs_ListItem">Single ~7MB Rust binary</li> |
|
| 19 | + | <li class="vocs_ListItem">Averages around ~10MB of RAM usage</li> |
|
| 20 | + | <li class="vocs_ListItem">Password authentication</li> |
|
| 21 | + | <li class="vocs_ListItem">Track USPS packages with custom labels</li> |
|
| 22 | + | <li class="vocs_ListItem">Delete packages you no longer want to track</li> |
|
| 23 | + | </ul> |
|
| 24 | + | <h2 class="vocs_H2 vocs_Heading"><div id="quickstart" class="vocs_Heading_slugTarget"></div>Quickstart<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/parcels#quickstart" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 25 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">git</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> clone</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> https://github.com/stevedylandev/andromeda.git</span></span> |
|
| 26 | + | <span class="line vocs_Span"><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span">cd</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> andromeda</span></span> |
|
| 27 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cp</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> apps/parcels/.env.example</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> .env</span></span> |
|
| 28 | + | <span class="line vocs_Span"><span style="color:#BDC4CC;--shiki-dark:#BDC4CC" class="vocs_Span"># Edit .env with your USPS API credentials and app password</span></span> |
|
| 29 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> run</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> parcels</span></span></code></pre></div></div> |
|
| 30 | + | <p class="vocs_Paragraph">You'll need a <a class="vocs_Anchor" href="https://developer.usps.com" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)">USPS Web Tools API</a> account to get your <code class="vocs_Code">USPS_CLIENT_ID</code> and <code class="vocs_Code">USPS_CLIENT_SECRET</code>.</p> |
|
| 31 | + | <h3 class="vocs_H3 vocs_Heading"><div id="environment-variables" class="vocs_Heading_slugTarget"></div>Environment Variables<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/parcels#environment-variables" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 32 | + | <table class="vocs_Table"><thead><tr class="vocs_TableRow"><th class="vocs_TableHeader">Variable</th><th class="vocs_TableHeader">Description</th><th class="vocs_TableHeader">Default</th></tr></thead><tbody><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">APP_PASSWORD</code></td><td class="vocs_TableCell">Password for login authentication</td><td class="vocs_TableCell"><em>required</em></td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">PARCELS_DB_PATH</code></td><td class="vocs_TableCell">SQLite database file path</td><td class="vocs_TableCell"><code class="vocs_Code">parcels.db</code></td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">USPS_CLIENT_ID</code></td><td class="vocs_TableCell">USPS OAuth2 client ID</td><td class="vocs_TableCell"><em>required</em></td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">USPS_CLIENT_SECRET</code></td><td class="vocs_TableCell">USPS OAuth2 client secret</td><td class="vocs_TableCell"><em>required</em></td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">PORT</code></td><td class="vocs_TableCell">Server port</td><td class="vocs_TableCell"><code class="vocs_Code">3000</code></td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">COOKIE_SECURE</code></td><td class="vocs_TableCell">Enable HTTPS-only cookies</td><td class="vocs_TableCell"><code class="vocs_Code">false</code></td></tr></tbody></table> |
|
| 33 | + | <h2 class="vocs_H2 vocs_Heading"><div id="structure" class="vocs_Heading_slugTarget"></div>Structure<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/parcels#structure" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 34 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">parcels/</span></span> |
|
| 35 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── src/</span></span> |
|
| 36 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── main.rs # Axum web server, routes, and app state</span></span> |
|
| 37 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── auth.rs # Password verification and session management</span></span> |
|
| 38 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── db.rs # SQLite database layer (packages, events, sessions)</span></span> |
|
| 39 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ └── usps.rs # USPS API integration with OAuth2 token caching</span></span> |
|
| 40 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── templates/ # Askama HTML templates</span></span> |
|
| 41 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── base.html # Base layout</span></span> |
|
| 42 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── index.html # Package list</span></span> |
|
| 43 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── detail.html # Package detail with tracking events</span></span> |
|
| 44 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── add.html # Add package form</span></span> |
|
| 45 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ └── login.html # Login page</span></span> |
|
| 46 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── static/ # Fonts, favicons, and images</span></span> |
|
| 47 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── Dockerfile</span></span> |
|
| 48 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">└── docker-compose.yml</span></span></code></pre></div></div> |
|
| 49 | + | <h2 class="vocs_H2 vocs_Heading"><div id="deployment" class="vocs_Heading_slugTarget"></div>Deployment<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/parcels#deployment" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 50 | + | <h3 class="vocs_H3 vocs_Heading"><div id="railway" class="vocs_Heading_slugTarget"></div>Railway<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/parcels#railway" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 51 | + | <p class="vocs_Paragraph"><a class="vocs_Anchor" href="https://railway.com/deploy/HNQUs4?referralCode=JGcIp6" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><img src="https://railway.com/button.svg" alt="Deploy on Railway"/></a></p> |
|
| 52 | + | <h3 class="vocs_H3 vocs_Heading"><div id="docker" class="vocs_Heading_slugTarget"></div>Docker<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/parcels#docker" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 53 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span">cd</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> apps/parcels</span></span> |
|
| 54 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cp</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> .env.example</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> .env</span></span> |
|
| 55 | + | <span class="line vocs_Span"><span style="color:#BDC4CC;--shiki-dark:#BDC4CC" class="vocs_Span"># Edit .env with your credentials</span></span> |
|
| 56 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">docker</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> compose</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> up</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -d</span></span></code></pre></div></div> |
|
| 57 | + | <p class="vocs_Paragraph">This will start Parcels on port <code class="vocs_Code">3000</code> with a persistent volume for the SQLite database.</p> |
|
| 58 | + | <h3 class="vocs_H3 vocs_Heading"><div id="binary" class="vocs_Heading_slugTarget"></div>Binary<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/parcels#binary" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 59 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> build</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> --release</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> parcels</span></span></code></pre></div></div> |
|
| 60 | + | <p class="vocs_Paragraph">The resulting binary is self-contained (~7MB). Copy it to your server with a configured <code class="vocs_Code">.env</code> file and run it directly.</p></article><footer class="vocs_Footer" data-layout="docs"><div class="vocs_Footer_container"></div></footer></div><div data-bottom-observer="true"></div></div></div> |
|
| 61 | + | </body> |
|
| 62 | + | </html> |
| 1 | + | <!doctype html> |
|
| 2 | + | <html lang="en" class="dark" data-vocs> |
|
| 3 | + | <head> |
|
| 4 | + | <meta charset="UTF-8" /> |
|
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
| 6 | + | <script src="/initializeTheme.iife.js"></script><link rel="preload" as="image" href="https://railway.com/button.svg"/><title>Shrink – Andromeda</title><meta property="og:type" content="website"/><meta property="og:title" content="Shrink"/><meta name="twitter:card" content="summary_large_image"/> |
|
| 7 | + | <script type="module" crossorigin src="/assets/index-DO6OtFZH.js"></script> |
|
| 8 | + | <link rel="stylesheet" crossorigin href="/assets/style-Dg8GuVX0.css"> |
|
| 9 | + | </head> |
|
| 10 | + | <body> |
|
| 11 | + | <span style="display: none;">Are you an LLM? Read <a href="/llms.txt">llms.txt</a> for a summary of the docs, or <a href="/llms-full.txt">llms-full.txt</a> for the full context.</span> |
|
| 12 | + | <div id="app"><div class="vocs_DocsLayout" data-layout="docs"><a class="vocs_SkipLink vocs_utils_visuallyHidden" href="/apps/shrink#vocs-content">Skip to content</a><div class="vocs_DocsLayout_gutterLeft"><aside class="vocs_Sidebar vocs_DocsLayout_sidebar"><div><div class="vocs_Sidebar_logoWrapper"><div class="vocs_Sidebar_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div><div class="vocs_Sidebar_divider"></div></div><nav class="vocs_Sidebar_navigation"><div class="vocs_Sidebar_group"><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Intro</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/quickstart" data-discover="true">Quickstart</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/what-is-andromeda" data-discover="true">What is Andromeda</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Apps</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/feeds" data-discover="true">Feeds</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/jotts" data-discover="true">Jotts</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/sipp" data-discover="true">Sipp</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/og" data-discover="true">OG</a><a data-active="true" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/shrink" data-discover="true">Shrink</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/parcels" data-discover="true">Parcels</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">DIY</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/stack" data-discover="true">Stack</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/skills" data-discover="true">Skills</a></div></section></div></nav></div><div class="vocs_Sidebar_footer"><div class="vocs_Sidebar_footerCurtain"></div><div class="vocs_Sidebar_footerContent"></div></div></aside></div><div class="vocs_DocsLayout_gutterTop vocs_DocsLayout_gutterTop_offsetLeftGutter"><div class="vocs_DesktopTopNav"><button class="vocs_DesktopSearch_search" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_4lj_" data-state="closed"><svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-top:2px"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>Search...<div class="vocs_DesktopSearch_searchCommand"><div style="background:currentColor;transform:rotate(45deg);width:1.5px;border-radius:2px;height:100%"></div></div></button><div class="vocs_DesktopTopNav_logoWrapper"><div class="vocs_DesktopTopNav_logo"><a style="align-items:center;display:flex;height:56px;margin-top:4px" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_DesktopTopNav_section"></div><div class="vocs_DesktopTopNav_section"></div></div><div class="vocs_MobileTopNav"><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group"><div class="vocs_MobileTopNav_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_MobileTopNav_group"><nav aria-label="Main" data-orientation="horizontal" dir="ltr" class="vocs_MobileTopNav_navigation vocs_NavigationMenu"><div style="position:relative"><ul data-orientation="horizontal" class="vocs_NavigationMenu_list" dir="ltr"></ul></div></nav><div class="vocs_MobileTopNav_navigation vocs_MobileTopNav_navigation_compact"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_kpj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger vocs_MobileTopNav_navigationItem">Menu<div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group" style="margin-right:-8px"><button class="vocs_MobileSearch_searchButton" type="button" aria-label="Search" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_39j_" data-state="closed"><svg width="21" height="21" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div></div></div></div><div class="vocs_DocsLayout_gutterTopCurtain vocs_DocsLayout_gutterTopCurtain_withSidebar"><div class="vocs_DesktopTopNav_curtain"></div><div class="vocs_MobileTopNav_curtain"><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_qj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger"><div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:13px"><svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 79 48" fill="none"><title>Menu</title><path fill="currentColor" d="M19.528 47.232h40.87c1.952 0 3.515-1.562 3.515-3.564a3.5 3.5 0 0 0-3.516-3.516H19.528a3.501 3.501 0 0 0-3.515 3.516c0 2.002 1.562 3.564 3.515 3.564ZM12.057 27.262h55.81a3.501 3.501 0 0 0 3.516-3.516 3.501 3.501 0 0 0-3.515-3.515h-55.81a3.501 3.501 0 0 0-3.516 3.515 3.501 3.501 0 0 0 3.515 3.516ZM4.391 7.34H75.29c2.002 0 3.515-1.563 3.515-3.516 0-2.002-1.513-3.564-3.515-3.564H4.39C2.438.26.876 1.822.876 3.824A3.501 3.501 0 0 0 4.39 7.34Z"></path></svg></div><div class="vocs_MobileTopNav_menuTitle">Shrink</div></button></div></div><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_5aj_" data-state="closed" class="vocs_MobileTopNav_outlineTrigger">On this page<div aria-label="On this page" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Right</title><path d="M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div></div><div class="vocs_DocsLayout_gutterRight vocs_DocsLayout_gutterRight_withSidebar"><aside class="vocs_Outline"><div class="vocs_AiCtaDropdown"><a class="vocs_Button_button vocs_AiCtaDropdown_buttonLeft vocs_AiCtaDropdown_button vocs_Button_button" href="https://chatgpt.com?hints=search&q=" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><div style="width:14px;height:14px"><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24"><title>OpenAI</title><path fill="currentColor" d="M22.282 9.821a6 6 0 0 0-.516-4.91a6.05 6.05 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a6 6 0 0 0-3.998 2.9a6.05 6.05 0 0 0 .743 7.097a5.98 5.98 0 0 0 .51 4.911a6.05 6.05 0 0 0 6.515 2.9A6 6 0 0 0 13.26 24a6.06 6.06 0 0 0 5.772-4.206a6 6 0 0 0 3.997-2.9a6.06 6.06 0 0 0-.747-7.073M13.26 22.43a4.48 4.48 0 0 1-2.876-1.04l.141-.081l4.779-2.758a.8.8 0 0 0 .392-.681v-6.737l2.02 1.168a.07.07 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494M3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085l4.783 2.759a.77.77 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646M2.34 7.896a4.5 4.5 0 0 1 2.366-1.973V11.6a.77.77 0 0 0 .388.677l5.815 3.354l-2.02 1.168a.08.08 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855l-5.833-3.387L15.119 7.2a.08.08 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667m2.01-3.023l-.141-.085l-4.774-2.782a.78.78 0 0 0-.785 0L9.409 9.23V6.897a.07.07 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135l-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08L8.704 5.46a.8.8 0 0 0-.393.681zm1.097-2.365l2.602-1.5l2.607 1.5v2.999l-2.597 1.5l-2.607-1.5Z"></path></svg></div>Ask in ChatGPT</a><button class="vocs_Button_button vocs_AiCtaDropdown_buttonRight vocs_AiCtaDropdown_button vocs_Button_button" type="button" id="radix-_R_9n_" aria-haspopup="menu" aria-expanded="false" data-state="closed"><div style="width:14px;height:14px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></aside></div><div id="vocs-content" class="vocs_DocsLayout_content vocs_DocsLayout_content_withSidebar vocs_DocsLayout_content_withTopNav"><article class="vocs_Content"><header class="vocs_Header"><h1 class="vocs_H1 vocs_Heading"><div id="shrink" class="vocs_Heading_slugTarget"></div>Shrink<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/shrink#shrink" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h1></header> |
|
| 13 | + | <p class="vocs_Paragraph">A minimal image compression app</p> |
|
| 14 | + | <h2 class="vocs_H2 vocs_Heading"><div id="overview" class="vocs_Heading_slugTarget"></div>Overview<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/shrink#overview" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 15 | + | <p class="vocs_Paragraph">A simple self-hosted tool for compressing and resizing images. Upload an image, set your desired quality and optional width, and download the compressed JPEG.</p> |
|
| 16 | + | <ul class="vocs_List vocs_List_unordered"> |
|
| 17 | + | <li class="vocs_ListItem">Single Rust binary</li> |
|
| 18 | + | <li class="vocs_ListItem">Compress images to JPEG with configurable quality (1-100)</li> |
|
| 19 | + | <li class="vocs_ListItem">Optional resize by width (preserves aspect ratio)</li> |
|
| 20 | + | <li class="vocs_ListItem">20MB upload limit</li> |
|
| 21 | + | </ul> |
|
| 22 | + | <h2 class="vocs_H2 vocs_Heading"><div id="quickstart" class="vocs_Heading_slugTarget"></div>Quickstart<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/shrink#quickstart" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 23 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">git</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> clone</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> https://github.com/stevedylandev/andromeda.git</span></span> |
|
| 24 | + | <span class="line vocs_Span"><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span">cd</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> andromeda</span></span> |
|
| 25 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> run</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> shrink</span></span></code></pre></div></div> |
|
| 26 | + | <h3 class="vocs_H3 vocs_Heading"><div id="environment-variables" class="vocs_Heading_slugTarget"></div>Environment Variables<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/shrink#environment-variables" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 27 | + | <table class="vocs_Table"><thead><tr class="vocs_TableRow"><th class="vocs_TableHeader">Variable</th><th class="vocs_TableHeader">Description</th><th class="vocs_TableHeader">Default</th></tr></thead><tbody><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">HOST</code></td><td class="vocs_TableCell">Server bind host</td><td class="vocs_TableCell"><code class="vocs_Code">127.0.0.1</code></td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">PORT</code></td><td class="vocs_TableCell">Server bind port</td><td class="vocs_TableCell"><code class="vocs_Code">3000</code></td></tr></tbody></table> |
|
| 28 | + | <h2 class="vocs_H2 vocs_Heading"><div id="structure" class="vocs_Heading_slugTarget"></div>Structure<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/shrink#structure" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 29 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">shrink/</span></span> |
|
| 30 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── src/</span></span> |
|
| 31 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── main.rs # Entry point and server startup</span></span> |
|
| 32 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ └── server.rs # Axum routes and image compression logic</span></span> |
|
| 33 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── templates/</span></span> |
|
| 34 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ └── index.html # Upload UI</span></span> |
|
| 35 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── static/ # Fonts and static assets</span></span> |
|
| 36 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── Dockerfile</span></span> |
|
| 37 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">└── docker-compose.yml</span></span></code></pre></div></div> |
|
| 38 | + | <h2 class="vocs_H2 vocs_Heading"><div id="deployment" class="vocs_Heading_slugTarget"></div>Deployment<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/shrink#deployment" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 39 | + | <h3 class="vocs_H3 vocs_Heading"><div id="railway" class="vocs_Heading_slugTarget"></div>Railway<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/shrink#railway" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 40 | + | <p class="vocs_Paragraph"><a class="vocs_Anchor" href="https://railway.com/deploy/enYUFb?referralCode=JGcIp6" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><img src="https://railway.com/button.svg" alt="Deploy on Railway"/></a></p> |
|
| 41 | + | <h3 class="vocs_H3 vocs_Heading"><div id="docker" class="vocs_Heading_slugTarget"></div>Docker<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/shrink#docker" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 42 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span">cd</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> apps/shrink</span></span> |
|
| 43 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">docker</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> compose</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> up</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -d</span></span></code></pre></div></div> |
|
| 44 | + | <p class="vocs_Paragraph">This will start Shrink on port <code class="vocs_Code">3000</code>.</p> |
|
| 45 | + | <h3 class="vocs_H3 vocs_Heading"><div id="binary" class="vocs_Heading_slugTarget"></div>Binary<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/shrink#binary" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 46 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> build</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> --release</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> shrink</span></span></code></pre></div></div> |
|
| 47 | + | <p class="vocs_Paragraph">The resulting binary is self-contained. Copy it to your server and run it directly.</p></article><footer class="vocs_Footer" data-layout="docs"><div class="vocs_Footer_container"></div></footer></div><div data-bottom-observer="true"></div></div></div> |
|
| 48 | + | </body> |
|
| 49 | + | </html> |
| 1 | + | <!doctype html> |
|
| 2 | + | <html lang="en" class="dark" data-vocs> |
|
| 3 | + | <head> |
|
| 4 | + | <meta charset="UTF-8" /> |
|
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
| 6 | + | <script src="/initializeTheme.iife.js"></script><link rel="preload" as="image" href="https://railway.com/button.svg"/><title>Sipp – Andromeda</title><meta property="og:type" content="website"/><meta property="og:title" content="Sipp"/><meta name="twitter:card" content="summary_large_image"/> |
|
| 7 | + | <script type="module" crossorigin src="/assets/index-DO6OtFZH.js"></script> |
|
| 8 | + | <link rel="stylesheet" crossorigin href="/assets/style-Dg8GuVX0.css"> |
|
| 9 | + | </head> |
|
| 10 | + | <body> |
|
| 11 | + | <span style="display: none;">Are you an LLM? Read <a href="/llms.txt">llms.txt</a> for a summary of the docs, or <a href="/llms-full.txt">llms-full.txt</a> for the full context.</span> |
|
| 12 | + | <div id="app"><div class="vocs_DocsLayout" data-layout="docs"><a class="vocs_SkipLink vocs_utils_visuallyHidden" href="/apps/sipp#vocs-content">Skip to content</a><div class="vocs_DocsLayout_gutterLeft"><aside class="vocs_Sidebar vocs_DocsLayout_sidebar"><div><div class="vocs_Sidebar_logoWrapper"><div class="vocs_Sidebar_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div><div class="vocs_Sidebar_divider"></div></div><nav class="vocs_Sidebar_navigation"><div class="vocs_Sidebar_group"><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Intro</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/quickstart" data-discover="true">Quickstart</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/what-is-andromeda" data-discover="true">What is Andromeda</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Apps</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/feeds" data-discover="true">Feeds</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/jotts" data-discover="true">Jotts</a><a data-active="true" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/sipp" data-discover="true">Sipp</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/og" data-discover="true">OG</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/shrink" data-discover="true">Shrink</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/parcels" data-discover="true">Parcels</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">DIY</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/stack" data-discover="true">Stack</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/skills" data-discover="true">Skills</a></div></section></div></nav></div><div class="vocs_Sidebar_footer"><div class="vocs_Sidebar_footerCurtain"></div><div class="vocs_Sidebar_footerContent"></div></div></aside></div><div class="vocs_DocsLayout_gutterTop vocs_DocsLayout_gutterTop_offsetLeftGutter"><div class="vocs_DesktopTopNav"><button class="vocs_DesktopSearch_search" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_4lj_" data-state="closed"><svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-top:2px"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>Search...<div class="vocs_DesktopSearch_searchCommand"><div style="background:currentColor;transform:rotate(45deg);width:1.5px;border-radius:2px;height:100%"></div></div></button><div class="vocs_DesktopTopNav_logoWrapper"><div class="vocs_DesktopTopNav_logo"><a style="align-items:center;display:flex;height:56px;margin-top:4px" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_DesktopTopNav_section"></div><div class="vocs_DesktopTopNav_section"></div></div><div class="vocs_MobileTopNav"><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group"><div class="vocs_MobileTopNav_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_MobileTopNav_group"><nav aria-label="Main" data-orientation="horizontal" dir="ltr" class="vocs_MobileTopNav_navigation vocs_NavigationMenu"><div style="position:relative"><ul data-orientation="horizontal" class="vocs_NavigationMenu_list" dir="ltr"></ul></div></nav><div class="vocs_MobileTopNav_navigation vocs_MobileTopNav_navigation_compact"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_kpj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger vocs_MobileTopNav_navigationItem">Menu<div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group" style="margin-right:-8px"><button class="vocs_MobileSearch_searchButton" type="button" aria-label="Search" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_39j_" data-state="closed"><svg width="21" height="21" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div></div></div></div><div class="vocs_DocsLayout_gutterTopCurtain vocs_DocsLayout_gutterTopCurtain_withSidebar"><div class="vocs_DesktopTopNav_curtain"></div><div class="vocs_MobileTopNav_curtain"><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_qj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger"><div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:13px"><svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 79 48" fill="none"><title>Menu</title><path fill="currentColor" d="M19.528 47.232h40.87c1.952 0 3.515-1.562 3.515-3.564a3.5 3.5 0 0 0-3.516-3.516H19.528a3.501 3.501 0 0 0-3.515 3.516c0 2.002 1.562 3.564 3.515 3.564ZM12.057 27.262h55.81a3.501 3.501 0 0 0 3.516-3.516 3.501 3.501 0 0 0-3.515-3.515h-55.81a3.501 3.501 0 0 0-3.516 3.515 3.501 3.501 0 0 0 3.515 3.516ZM4.391 7.34H75.29c2.002 0 3.515-1.563 3.515-3.516 0-2.002-1.513-3.564-3.515-3.564H4.39C2.438.26.876 1.822.876 3.824A3.501 3.501 0 0 0 4.39 7.34Z"></path></svg></div><div class="vocs_MobileTopNav_menuTitle">Sipp</div></button></div></div><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_5aj_" data-state="closed" class="vocs_MobileTopNav_outlineTrigger">On this page<div aria-label="On this page" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Right</title><path d="M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div></div><div class="vocs_DocsLayout_gutterRight vocs_DocsLayout_gutterRight_withSidebar"><aside class="vocs_Outline"><div class="vocs_AiCtaDropdown"><a class="vocs_Button_button vocs_AiCtaDropdown_buttonLeft vocs_AiCtaDropdown_button vocs_Button_button" href="https://chatgpt.com?hints=search&q=" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><div style="width:14px;height:14px"><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24"><title>OpenAI</title><path fill="currentColor" d="M22.282 9.821a6 6 0 0 0-.516-4.91a6.05 6.05 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a6 6 0 0 0-3.998 2.9a6.05 6.05 0 0 0 .743 7.097a5.98 5.98 0 0 0 .51 4.911a6.05 6.05 0 0 0 6.515 2.9A6 6 0 0 0 13.26 24a6.06 6.06 0 0 0 5.772-4.206a6 6 0 0 0 3.997-2.9a6.06 6.06 0 0 0-.747-7.073M13.26 22.43a4.48 4.48 0 0 1-2.876-1.04l.141-.081l4.779-2.758a.8.8 0 0 0 .392-.681v-6.737l2.02 1.168a.07.07 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494M3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085l4.783 2.759a.77.77 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646M2.34 7.896a4.5 4.5 0 0 1 2.366-1.973V11.6a.77.77 0 0 0 .388.677l5.815 3.354l-2.02 1.168a.08.08 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855l-5.833-3.387L15.119 7.2a.08.08 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667m2.01-3.023l-.141-.085l-4.774-2.782a.78.78 0 0 0-.785 0L9.409 9.23V6.897a.07.07 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135l-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08L8.704 5.46a.8.8 0 0 0-.393.681zm1.097-2.365l2.602-1.5l2.607 1.5v2.999l-2.597 1.5l-2.607-1.5Z"></path></svg></div>Ask in ChatGPT</a><button class="vocs_Button_button vocs_AiCtaDropdown_buttonRight vocs_AiCtaDropdown_button vocs_Button_button" type="button" id="radix-_R_9n_" aria-haspopup="menu" aria-expanded="false" data-state="closed"><div style="width:14px;height:14px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></aside></div><div id="vocs-content" class="vocs_DocsLayout_content vocs_DocsLayout_content_withSidebar vocs_DocsLayout_content_withTopNav"><article class="vocs_Content"><header class="vocs_Header"><h1 class="vocs_H1 vocs_Heading"><div id="sipp" class="vocs_Heading_slugTarget"></div>Sipp<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#sipp" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h1></header> |
|
| 13 | + | <p class="vocs_Paragraph">Minimal code sharing</p> |
|
| 14 | + | <h2 class="vocs_H2 vocs_Heading"><div id="overview" class="vocs_Heading_slugTarget"></div>Overview<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#overview" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 15 | + | <p class="vocs_Paragraph">A single binary for code sharing with a web server and interactive TUI.</p> |
|
| 16 | + | <ul class="vocs_List vocs_List_unordered"> |
|
| 17 | + | <li class="vocs_ListItem">Create snippets and share on the web</li> |
|
| 18 | + | <li class="vocs_ListItem">Raw output for CLI tools -- <code class="vocs_Code">curl</code>, <code class="vocs_Code">wget</code>, and <code class="vocs_Code">httpie</code> get plain text automatically</li> |
|
| 19 | + | <li class="vocs_ListItem">Interactive TUI with authenticated access for snippet management</li> |
|
| 20 | + | <li class="vocs_ListItem">Minimal, fast, and low memory consumption</li> |
|
| 21 | + | </ul> |
|
| 22 | + | <aside class="vocs_Aside vocs_Callout vocs_Callout_warning"><div class="vocs_Callout_icon"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Exclamation</title><path d="M8.4449 0.608765C8.0183 -0.107015 6.9817 -0.107015 6.55509 0.608766L0.161178 11.3368C-0.275824 12.07 0.252503 13 1.10608 13H13.8939C14.7475 13 15.2758 12.07 14.8388 11.3368L8.4449 0.608765ZM7.4141 1.12073C7.45288 1.05566 7.54712 1.05566 7.5859 1.12073L13.9798 11.8488C14.0196 11.9154 13.9715 12 13.8939 12H1.10608C1.02849 12 0.980454 11.9154 1.02018 11.8488L7.4141 1.12073ZM6.8269 4.48611C6.81221 4.10423 7.11783 3.78663 7.5 3.78663C7.88217 3.78663 8.18778 4.10423 8.1731 4.48612L8.01921 8.48701C8.00848 8.766 7.7792 8.98664 7.5 8.98664C7.2208 8.98664 6.99151 8.766 6.98078 8.48701L6.8269 4.48611ZM8.24989 10.476C8.24989 10.8902 7.9141 11.226 7.49989 11.226C7.08567 11.226 6.74989 10.8902 6.74989 10.476C6.74989 10.0618 7.08567 9.72599 7.49989 9.72599C7.9141 9.72599 8.24989 10.0618 8.24989 10.476Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div><div class="vocs_Callout_content"><p class="vocs_Paragraph">A small demo instance runs at <a class="vocs_Anchor" href="https://sipp.so" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)">sipp.so</a>. All snippets created there are public and might be deleted at any time; host your own instance with your own API key for personal use!</p></div></aside> |
|
| 23 | + | <h2 class="vocs_H2 vocs_Heading"><div id="quickstart" class="vocs_Heading_slugTarget"></div>Quickstart<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#quickstart" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 24 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> install</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> sipp-so</span></span> |
|
| 25 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">sipp</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> --help</span></span></code></pre></div></div> |
|
| 26 | + | <p class="vocs_Paragraph">Start a server and create a snippet:</p> |
|
| 27 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">sipp</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> server</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> --port</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> 3000</span></span></code></pre></div></div> |
|
| 28 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#BDC4CC;--shiki-dark:#BDC4CC" class="vocs_Span"># Path to file</span></span> |
|
| 29 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">sipp</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> path/to/file.rs</span></span> |
|
| 30 | + | <span class="line vocs_Span" data-empty-line="true"> </span> |
|
| 31 | + | <span class="line vocs_Span"><span style="color:#BDC4CC;--shiki-dark:#BDC4CC" class="vocs_Span"># Or use the interactive TUI</span></span> |
|
| 32 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">sipp</span></span></code></pre></div></div> |
|
| 33 | + | <h3 class="vocs_H3 vocs_Heading"><div id="install" class="vocs_Heading_slugTarget"></div>Install<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#install" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 34 | + | <p class="vocs_Paragraph">Sipp can be installed several ways:</p> |
|
| 35 | + | <h4 class="vocs_H4 vocs_Heading"><div id="homebrew" class="vocs_Heading_slugTarget"></div>Homebrew<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#homebrew" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h4> |
|
| 36 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">brew</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> install</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> stevedylandev/tap/sipp-so</span></span></code></pre></div></div> |
|
| 37 | + | <h4 class="vocs_H4 vocs_Heading"><div id="cargo" class="vocs_Heading_slugTarget"></div>Cargo<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#cargo" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h4> |
|
| 38 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> install</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> sipp-so</span></span></code></pre></div></div> |
|
| 39 | + | <h4 class="vocs_H4 vocs_Heading"><div id="releases" class="vocs_Heading_slugTarget"></div>Releases<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#releases" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h4> |
|
| 40 | + | <p class="vocs_Paragraph">Visit the <a class="vocs_Anchor" href="https://github.com/stevedylandev/sipp/releases" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)">releases</a> page for binaries and install scripts.</p> |
|
| 41 | + | <h2 class="vocs_H2 vocs_Heading"><div id="cli" class="vocs_Heading_slugTarget"></div>CLI<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#cli" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 42 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">sipp [</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">OPTIONS</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">] [</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">FILE</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">] [</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">COMMAND</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">]</span></span></code></pre></div></div> |
|
| 43 | + | <h3 class="vocs_H3 vocs_Heading"><div id="commands" class="vocs_Heading_slugTarget"></div>Commands<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#commands" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 44 | + | <table class="vocs_Table"><thead><tr class="vocs_TableRow"><th class="vocs_TableHeader">Command</th><th class="vocs_TableHeader">Description</th></tr></thead><tbody><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">server</code></td><td class="vocs_TableCell">Start the web server</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">tui</code></td><td class="vocs_TableCell">Launch the interactive TUI</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">auth</code></td><td class="vocs_TableCell">Save remote URL and API key to config file</td></tr></tbody></table> |
|
| 45 | + | <h3 class="vocs_H3 vocs_Heading"><div id="arguments" class="vocs_Heading_slugTarget"></div>Arguments<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#arguments" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 46 | + | <table class="vocs_Table"><thead><tr class="vocs_TableRow"><th class="vocs_TableHeader">Argument</th><th class="vocs_TableHeader">Description</th></tr></thead><tbody><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">[FILE]</code></td><td class="vocs_TableCell">File path to create a snippet from</td></tr></tbody></table> |
|
| 47 | + | <h3 class="vocs_H3 vocs_Heading"><div id="options" class="vocs_Heading_slugTarget"></div>Options<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#options" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 48 | + | <table class="vocs_Table"><thead><tr class="vocs_TableRow"><th class="vocs_TableHeader">Option</th><th class="vocs_TableHeader">Description</th></tr></thead><tbody><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">-r, --remote <URL></code></td><td class="vocs_TableCell">Remote server URL (env: <code class="vocs_Code">SIPP_REMOTE_URL</code>)</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">-k, --api-key <KEY></code></td><td class="vocs_TableCell">API key for authenticated operations (env: <code class="vocs_Code">SIPP_API_KEY</code>)</td></tr></tbody></table> |
|
| 49 | + | <h2 class="vocs_H2 vocs_Heading"><div id="server" class="vocs_Heading_slugTarget"></div>Server<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#server" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 50 | + | <p class="vocs_Paragraph">Sipp includes a built-in web server powered by Axum. Start it with:</p> |
|
| 51 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">sipp</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> server</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> --port</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> 3000</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> --host</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> localhost</span></span></code></pre></div></div> |
|
| 52 | + | <h3 class="vocs_H3 vocs_Heading"><div id="environment-variables" class="vocs_Heading_slugTarget"></div>Environment Variables<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#environment-variables" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 53 | + | <table class="vocs_Table"><thead><tr class="vocs_TableRow"><th class="vocs_TableHeader">Variable</th><th class="vocs_TableHeader">Description</th></tr></thead><tbody><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">SIPP_API_KEY</code></td><td class="vocs_TableCell">API key for protecting endpoints</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">SIPP_AUTH_ENDPOINTS</code></td><td class="vocs_TableCell">Comma-separated list of endpoints requiring auth: <code class="vocs_Code">api_list</code>, <code class="vocs_Code">api_create</code>, <code class="vocs_Code">api_get</code>, <code class="vocs_Code">api_delete</code>, <code class="vocs_Code">all</code>, or <code class="vocs_Code">none</code> (defaults to <code class="vocs_Code">api_delete,api_list</code>)</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">SIPP_MAX_CONTENT_SIZE</code></td><td class="vocs_TableCell">Maximum snippet content size in bytes (defaults to <code class="vocs_Code">512000</code> / 500 KB)</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">SIPP_DB_PATH</code></td><td class="vocs_TableCell">Custom path for the SQLite database file (defaults to <code class="vocs_Code">sipp.sqlite</code>)</td></tr></tbody></table> |
|
| 54 | + | <h3 class="vocs_H3 vocs_Heading"><div id="api-endpoints" class="vocs_Heading_slugTarget"></div>API Endpoints<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#api-endpoints" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 55 | + | <table class="vocs_Table"><thead><tr class="vocs_TableRow"><th class="vocs_TableHeader">Method</th><th class="vocs_TableHeader">Endpoint</th><th class="vocs_TableHeader">Description</th></tr></thead><tbody><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">GET</code></td><td class="vocs_TableCell"><code class="vocs_Code">/api/snippets</code></td><td class="vocs_TableCell">List all snippets</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">POST</code></td><td class="vocs_TableCell"><code class="vocs_Code">/api/snippets</code></td><td class="vocs_TableCell">Create a snippet (<code class="vocs_Code">{"name": "...", "content": "..."}</code>)</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">GET</code></td><td class="vocs_TableCell"><code class="vocs_Code">/api/snippets/{short_id}</code></td><td class="vocs_TableCell">Get a snippet by ID</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">PUT</code></td><td class="vocs_TableCell"><code class="vocs_Code">/api/snippets/{short_id}</code></td><td class="vocs_TableCell">Update a snippet</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">DELETE</code></td><td class="vocs_TableCell"><code class="vocs_Code">/api/snippets/{short_id}</code></td><td class="vocs_TableCell">Delete a snippet by ID</td></tr></tbody></table> |
|
| 56 | + | <p class="vocs_Paragraph">Authenticated endpoints require an <code class="vocs_Code">x-api-key</code> header.</p> |
|
| 57 | + | <h3 class="vocs_H3 vocs_Heading"><div id="raw-output-for-cli-tools" class="vocs_Heading_slugTarget"></div>Raw Output for CLI Tools<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#raw-output-for-cli-tools" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 58 | + | <p class="vocs_Paragraph">When you access a snippet URL (<code class="vocs_Code">/s/{short_id}</code>) with <code class="vocs_Code">curl</code>, <code class="vocs_Code">wget</code>, or <code class="vocs_Code">httpie</code>, the server returns the raw content as plain text instead of HTML:</p> |
|
| 59 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">curl</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> https://sipp.so/s/abc123</span></span></code></pre></div></div> |
|
| 60 | + | <h2 class="vocs_H2 vocs_Heading"><div id="tui" class="vocs_Heading_slugTarget"></div>TUI<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#tui" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 61 | + | <p class="vocs_Paragraph">The Sipp TUI makes it easy to create, copy, share, and manage your snippets either locally or remotely.</p> |
|
| 62 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#BDC4CC;--shiki-dark:#BDC4CC" class="vocs_Span"># Launch TUI (default behavior when no file argument is given)</span></span> |
|
| 63 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">sipp</span></span> |
|
| 64 | + | <span class="line vocs_Span" data-empty-line="true"> </span> |
|
| 65 | + | <span class="line vocs_Span"><span style="color:#BDC4CC;--shiki-dark:#BDC4CC" class="vocs_Span"># Or explicitly</span></span> |
|
| 66 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">sipp</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> tui</span></span> |
|
| 67 | + | <span class="line vocs_Span" data-empty-line="true"> </span> |
|
| 68 | + | <span class="line vocs_Span"><span style="color:#BDC4CC;--shiki-dark:#BDC4CC" class="vocs_Span"># With remote options</span></span> |
|
| 69 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">sipp</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -r</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> https://sipp.so</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -k</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> your-api-key</span></span></code></pre></div></div> |
|
| 70 | + | <h3 class="vocs_H3 vocs_Heading"><div id="local-access" class="vocs_Heading_slugTarget"></div>Local Access<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#local-access" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 71 | + | <p class="vocs_Paragraph">If you are running <code class="vocs_Code">sipp</code> in the same directory as the <code class="vocs_Code">sipp.sqlite</code> file created by the server instance, the TUI will automatically access the database locally.</p> |
|
| 72 | + | <h3 class="vocs_H3 vocs_Heading"><div id="remote-access" class="vocs_Heading_slugTarget"></div>Remote Access<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#remote-access" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 73 | + | <p class="vocs_Paragraph">To access a remote instance:</p> |
|
| 74 | + | <ul class="vocs_List vocs_List_unordered"> |
|
| 75 | + | <li class="vocs_ListItem">Set the <code class="vocs_Code">SIPP_API_KEY</code> variable in your server instance</li> |
|
| 76 | + | <li class="vocs_ListItem">Run <code class="vocs_Code">sipp auth</code> to enter your server URL and API key, stored under <code class="vocs_Code">$HOME/.config/sipp</code></li> |
|
| 77 | + | </ul> |
|
| 78 | + | <h3 class="vocs_H3 vocs_Heading"><div id="keybindings" class="vocs_Heading_slugTarget"></div>Keybindings<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#keybindings" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 79 | + | <table class="vocs_Table"><thead><tr class="vocs_TableRow"><th class="vocs_TableHeader">Key</th><th class="vocs_TableHeader">Action</th></tr></thead><tbody><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">j</code>/<code class="vocs_Code">Down</code></td><td class="vocs_TableCell">Move down / Scroll down</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">k</code>/<code class="vocs_Code">Up</code></td><td class="vocs_TableCell">Move up / Scroll up</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">Enter</code></td><td class="vocs_TableCell">Focus content pane</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">Esc</code></td><td class="vocs_TableCell">Back / Quit</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">y</code></td><td class="vocs_TableCell">Copy snippet content</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">Y</code></td><td class="vocs_TableCell">Copy snippet link</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">o</code></td><td class="vocs_TableCell">Open in browser</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">e</code></td><td class="vocs_TableCell">Edit snippet</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">d</code></td><td class="vocs_TableCell">Delete snippet</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">c</code></td><td class="vocs_TableCell">Create snippet</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">/</code></td><td class="vocs_TableCell">Search snippets</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">r</code></td><td class="vocs_TableCell">Refresh snippets (remote only)</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">q</code></td><td class="vocs_TableCell">Quit</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">?</code></td><td class="vocs_TableCell">Toggle help</td></tr></tbody></table> |
|
| 80 | + | <h2 class="vocs_H2 vocs_Heading"><div id="structure" class="vocs_Heading_slugTarget"></div>Structure<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#structure" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 81 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">sipp/</span></span> |
|
| 82 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── src/</span></span> |
|
| 83 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── main.rs # CLI argument parsing and entry point</span></span> |
|
| 84 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── lib.rs # Library exports</span></span> |
|
| 85 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── server.rs # Axum web server, routes, and templates</span></span> |
|
| 86 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── tui.rs # Interactive terminal UI</span></span> |
|
| 87 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── db.rs # SQLite database layer</span></span> |
|
| 88 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── backend.rs # Local/remote backend abstraction</span></span> |
|
| 89 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── config.rs # Config file management</span></span> |
|
| 90 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ └── highlight.rs # Syntax highlighting with custom themes</span></span> |
|
| 91 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── templates/ # Askama HTML templates</span></span> |
|
| 92 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── static/ # Fonts, favicons, and styles</span></span> |
|
| 93 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── Dockerfile</span></span> |
|
| 94 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">└── docker-compose.yml</span></span></code></pre></div></div> |
|
| 95 | + | <h2 class="vocs_H2 vocs_Heading"><div id="deployment" class="vocs_Heading_slugTarget"></div>Deployment<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#deployment" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 96 | + | <h3 class="vocs_H3 vocs_Heading"><div id="railway" class="vocs_Heading_slugTarget"></div>Railway<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#railway" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 97 | + | <p class="vocs_Paragraph"><a class="vocs_Anchor" href="https://railway.com/deploy/Axcf_D?referralCode=JGcIp6" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><img src="https://railway.com/button.svg" alt="Deploy on Railway"/></a></p> |
|
| 98 | + | <h3 class="vocs_H3 vocs_Heading"><div id="docker" class="vocs_Heading_slugTarget"></div>Docker<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#docker" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 99 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">SIPP_API_KEY</span><span style="color:#FF9492;--shiki-dark:#FF9492" class="vocs_Span">=</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">your-secret-key</span><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span"> docker</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> compose</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> up</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -d</span></span></code></pre></div></div> |
|
| 100 | + | <h3 class="vocs_H3 vocs_Heading"><div id="binary" class="vocs_Heading_slugTarget"></div>Binary<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/apps/sipp#binary" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 101 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> build</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> --release</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> sipp</span></span></code></pre></div></div> |
|
| 102 | + | <p class="vocs_Paragraph">The resulting binary is self-contained with all assets embedded. Copy it to your server with your environment variables configured and run it directly.</p></article><footer class="vocs_Footer" data-layout="docs"><div class="vocs_Footer_container"></div></footer></div><div data-bottom-observer="true"></div></div></div> |
|
| 103 | + | </body> |
|
| 104 | + | </html> |
| 1 | + | import{u as n,j as e}from"./index-DO6OtFZH.js";const d={title:"Feeds",description:"undefined"};function r(i){const s={a:"a",code:"code",div:"div",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",li:"li",p:"p",pre:"pre",span:"span",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...n(),...i.components};return e.jsxs(e.Fragment,{children:[e.jsx(s.header,{children:e.jsxs(s.h1,{id:"feeds",children:["Feeds",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#feeds",children:e.jsx(s.div,{"data-autolink-icon":!0})})]})}),` |
|
| 2 | + | `,e.jsx(s.p,{children:"Minimal RSS Feeds"}),` |
|
| 3 | + | `,e.jsxs(s.h2,{id:"overview",children:["Overview",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#overview",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 4 | + | `,e.jsx(s.p,{children:"Feeds is a minimal RSS reader that mimics the original experience of RSS. It's just a list of posts. No categories, no marking a post read or unread, and there is no in-app reading. With this approach you have to read the post on the author's personal website and experience it in its original context."}),` |
|
| 5 | + | `,e.jsxs(s.ul,{children:[` |
|
| 6 | + | `,e.jsx(s.li,{children:"Single Rust binary with embedded assets"}),` |
|
| 7 | + | `,e.jsx(s.li,{children:"Multiple feed sources: URL params, OPML file, or FreshRSS API"}),` |
|
| 8 | + | `,e.jsx(s.li,{children:"Password-protected admin panel for managing subscriptions"}),` |
|
| 9 | + | `,e.jsx(s.li,{children:"Feeds API with JSON and OPML export"}),` |
|
| 10 | + | `,e.jsx(s.li,{children:"Dark themed UI with Commit Mono font"}),` |
|
| 11 | + | `]}),` |
|
| 12 | + | `,e.jsxs(s.h2,{id:"quickstart",children:["Quickstart",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#quickstart",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 13 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsxs(s.code,{children:[e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"git"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" clone"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" https://github.com/stevedylandev/andromeda.git"})]}),` |
|
| 14 | + | `,e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:"cd"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" andromeda"})]}),` |
|
| 15 | + | `,e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" run"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" feeds"})]}),` |
|
| 16 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#BDC4CC","--shiki-dark":"#BDC4CC"},children:"# Server running on http://localhost:3000"})})]})})}),` |
|
| 17 | + | `,e.jsxs(s.h3,{id:"environment-variables",children:["Environment Variables",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#environment-variables",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 18 | + | `,e.jsxs(s.table,{children:[e.jsx(s.thead,{children:e.jsxs(s.tr,{children:[e.jsx(s.th,{children:"Variable"}),e.jsx(s.th,{children:"Description"}),e.jsx(s.th,{children:"Default"})]})}),e.jsxs(s.tbody,{children:[e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"FRESHRSS_URL"})}),e.jsx(s.td,{children:"URL of your FreshRSS instance"}),e.jsx(s.td,{children:"--"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"FRESHRSS_USERNAME"})}),e.jsx(s.td,{children:"FreshRSS username"}),e.jsx(s.td,{children:"--"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"FRESHRSS_PASSWORD"})}),e.jsx(s.td,{children:"FreshRSS password"}),e.jsx(s.td,{children:"--"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"ADMIN_PASSWORD"})}),e.jsx(s.td,{children:"Password for the admin panel"}),e.jsx(s.td,{children:"--"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"COOKIE_SECURE"})}),e.jsx(s.td,{children:"Enable HTTPS-only cookies"}),e.jsx(s.td,{children:e.jsx(s.code,{children:"false"})})]})]})]}),` |
|
| 19 | + | `,e.jsxs(s.h2,{id:"usage",children:["Usage",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#usage",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 20 | + | `,e.jsx(s.p,{children:"There are several built-in ways to source RSS feeds."}),` |
|
| 21 | + | `,e.jsxs(s.h3,{id:"url-query-param",children:["URL Query Param",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#url-query-param",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 22 | + | `,e.jsx(s.p,{children:"Once you have the app running you can add the following to the URL to source an RSS feed:"}),` |
|
| 23 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsx(s.code,{children:e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"?url=https://bearblog.dev/discover/feed/"})})})})}),` |
|
| 24 | + | `,e.jsx(s.p,{children:"You can also add multiple URLs by using commas to separate them:"}),` |
|
| 25 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsx(s.code,{children:e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"?urls=https://bearblog.dev/discover/feed/,https://bearblog.stevedylan.dev/feed/"})})})})}),` |
|
| 26 | + | `,e.jsxs(s.h3,{id:"opml-file",children:["OPML File",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#opml-file",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 27 | + | `,e.jsxs(s.p,{children:["If you save a ",e.jsx(s.code,{children:"feeds.opml"})," file in the root of the project the app will automatically source it and fetch the posts for the feeds inside."]}),` |
|
| 28 | + | `,e.jsxs(s.h3,{id:"freshrss-api",children:["FreshRSS API",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#freshrss-api",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 29 | + | `,e.jsx(s.p,{children:"If neither of the above are provided the app will default to using a FreshRSS API instance. Set the following environment variables:"}),` |
|
| 30 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsxs(s.code,{children:[e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"FRESHRSS_URL="})}),` |
|
| 31 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"FRESHRSS_USERNAME="})}),` |
|
| 32 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"FRESHRSS_PASSWORD="})})]})})}),` |
|
| 33 | + | `,e.jsxs(s.h3,{id:"admin-panel",children:["Admin Panel",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#admin-panel",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 34 | + | `,e.jsxs(s.p,{children:["Feeds includes a password-protected admin panel at ",e.jsx(s.code,{children:"/admin"})," for managing your FreshRSS subscriptions. Set the ",e.jsx(s.code,{children:"ADMIN_PASSWORD"})," environment variable to enable it. From the admin panel you can view your current subscriptions and add new feeds directly to your FreshRSS instance."]}),` |
|
| 35 | + | `,e.jsxs(s.h3,{id:"feeds-api",children:["Feeds API",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#feeds-api",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 36 | + | `,e.jsxs(s.p,{children:["The ",e.jsx(s.code,{children:"/feeds"})," endpoint exports your FreshRSS subscriptions in JSON or OPML format:"]}),` |
|
| 37 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsxs(s.code,{children:[e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"/feeds?format=json"})}),` |
|
| 38 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"/feeds?format=opml"})})]})})}),` |
|
| 39 | + | `,e.jsxs(s.h2,{id:"structure",children:["Structure",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#structure",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 40 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsxs(s.code,{children:[e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"feeds/"})}),` |
|
| 41 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── src/"})}),` |
|
| 42 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── main.rs # Axum server with routing, templates, and static asset serving"})}),` |
|
| 43 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── feeds.rs # Feed fetching, OPML parsing, and FreshRSS API integration"})}),` |
|
| 44 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── auth.rs # Session-based authentication with constant-time password verification"})}),` |
|
| 45 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ └── models.rs # Data structures for feeds and FreshRSS responses"})}),` |
|
| 46 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── templates/ # Askama HTML templates"})}),` |
|
| 47 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── assets/ # Static assets embedded at compile time via rust-embed"})}),` |
|
| 48 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── Dockerfile"})}),` |
|
| 49 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"└── docker-compose.yml"})})]})})}),` |
|
| 50 | + | `,e.jsxs(s.h2,{id:"deployment",children:["Deployment",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#deployment",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 51 | + | `,e.jsxs(s.h3,{id:"railway",children:["Railway",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#railway",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 52 | + | `,e.jsx(s.p,{children:e.jsx(s.a,{href:"https://railway.com/deploy/Ezvmhx?referralCode=JGcIp6",children:e.jsx(s.img,{src:"https://railway.com/button.svg",alt:"Deploy on Railway"})})}),` |
|
| 53 | + | `,e.jsxs(s.h3,{id:"docker",children:["Docker",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#docker",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 54 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsxs(s.code,{children:[e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:"cd"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" apps/feeds"})]}),` |
|
| 55 | + | `,e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cp"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" .env.sample"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" .env"})]}),` |
|
| 56 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#BDC4CC","--shiki-dark":"#BDC4CC"},children:"# Edit .env with your credentials"})}),` |
|
| 57 | + | `,e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"docker"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" compose"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" up"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -d"})]})]})})}),` |
|
| 58 | + | `,e.jsxs(s.h3,{id:"binary",children:["Binary",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#binary",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 59 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsx(s.code,{children:e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" build"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" --release"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" feeds"})]})})})}),` |
|
| 60 | + | `,e.jsxs(s.p,{children:["The resulting binary is self-contained with all assets embedded. Copy it to your server with a configured ",e.jsx(s.code,{children:".env"})," file and run it directly."]})]})}function l(i={}){const{wrapper:s}={...n(),...i.components};return s?e.jsx(s,{...i,children:e.jsx(r,{...i})}):r(i)}export{l as default,d as frontmatter}; |
| 1 | + | function W1(t,a){for(var o=0;o<a.length;o++){const i=a[o];if(typeof i!="string"&&!Array.isArray(i)){for(const s in i)if(s!=="default"&&!(s in t)){const u=Object.getOwnPropertyDescriptor(i,s);u&&Object.defineProperty(t,s,u.get?u:{enumerable:!0,get:()=>i[s]})}}}return Object.freeze(Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}))}(function(){const a=document.createElement("link").relList;if(a&&a.supports&&a.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))i(s);new MutationObserver(s=>{for(const u of s)if(u.type==="childList")for(const c of u.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&i(c)}).observe(document,{childList:!0,subtree:!0});function o(s){const u={};return s.integrity&&(u.integrity=s.integrity),s.referrerPolicy&&(u.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?u.credentials="include":s.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function i(s){if(s.ep)return;s.ep=!0;const u=o(s);fetch(s.href,u)}})();function El(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var C2={exports:{}},al={};var qv;function $4(){if(qv)return al;qv=1;var t=Symbol.for("react.transitional.element"),a=Symbol.for("react.fragment");function o(i,s,u){var c=null;if(u!==void 0&&(c=""+u),s.key!==void 0&&(c=""+s.key),"key"in s){u={};for(var d in s)d!=="key"&&(u[d]=s[d])}else u=s;return s=u.ref,{$$typeof:t,type:i,key:c,ref:s!==void 0?s:null,props:u}}return al.Fragment=a,al.jsx=o,al.jsxs=o,al}var Gv;function V4(){return Gv||(Gv=1,C2.exports=$4()),C2.exports}var g=V4();const q4=El(g),G4=W1({__proto__:null,default:q4},[g]);var b2={exports:{}},Fe={};var Yv;function Y4(){if(Yv)return Fe;Yv=1;var t=Symbol.for("react.transitional.element"),a=Symbol.for("react.portal"),o=Symbol.for("react.fragment"),i=Symbol.for("react.strict_mode"),s=Symbol.for("react.profiler"),u=Symbol.for("react.consumer"),c=Symbol.for("react.context"),d=Symbol.for("react.forward_ref"),v=Symbol.for("react.suspense"),m=Symbol.for("react.memo"),A=Symbol.for("react.lazy"),p=Symbol.for("react.activity"),C=Symbol.iterator;function b(L){return L===null||typeof L!="object"?null:(L=C&&L[C]||L["@@iterator"],typeof L=="function"?L:null)}var S={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},x=Object.assign,w={};function D(L,$,ne){this.props=L,this.context=$,this.refs=w,this.updater=ne||S}D.prototype.isReactComponent={},D.prototype.setState=function(L,$){if(typeof L!="object"&&typeof L!="function"&&L!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,L,$,"setState")},D.prototype.forceUpdate=function(L){this.updater.enqueueForceUpdate(this,L,"forceUpdate")};function T(){}T.prototype=D.prototype;function R(L,$,ne){this.props=L,this.context=$,this.refs=w,this.updater=ne||S}var _=R.prototype=new T;_.constructor=R,x(_,D.prototype),_.isPureReactComponent=!0;var N=Array.isArray;function j(){}var F={H:null,A:null,T:null,S:null},O=Object.prototype.hasOwnProperty;function I(L,$,ne){var ie=ne.ref;return{$$typeof:t,type:L,key:$,ref:ie!==void 0?ie:null,props:ne}}function re(L,$){return I(L.type,$,L.props)}function pe(L){return typeof L=="object"&&L!==null&&L.$$typeof===t}function ce(L){var $={"=":"=0",":":"=2"};return"$"+L.replace(/[=:]/g,function(ne){return $[ne]})}var de=/\/+/g;function J(L,$){return typeof L=="object"&&L!==null&&L.key!=null?ce(""+L.key):$.toString(36)}function fe(L){switch(L.status){case"fulfilled":return L.value;case"rejected":throw L.reason;default:switch(typeof L.status=="string"?L.then(j,j):(L.status="pending",L.then(function($){L.status==="pending"&&(L.status="fulfilled",L.value=$)},function($){L.status==="pending"&&(L.status="rejected",L.reason=$)})),L.status){case"fulfilled":return L.value;case"rejected":throw L.reason}}throw L}function U(L,$,ne,ie,Ae){var Se=typeof L;(Se==="undefined"||Se==="boolean")&&(L=null);var ue=!1;if(L===null)ue=!0;else switch(Se){case"bigint":case"string":case"number":ue=!0;break;case"object":switch(L.$$typeof){case t:case a:ue=!0;break;case A:return ue=L._init,U(ue(L._payload),$,ne,ie,Ae)}}if(ue)return Ae=Ae(L),ue=ie===""?"."+J(L,0):ie,N(Ae)?(ne="",ue!=null&&(ne=ue.replace(de,"$&/")+"/"),U(Ae,$,ne,"",function(lt){return lt})):Ae!=null&&(pe(Ae)&&(Ae=re(Ae,ne+(Ae.key==null||L&&L.key===Ae.key?"":(""+Ae.key).replace(de,"$&/")+"/")+ue)),$.push(Ae)),1;ue=0;var q=ie===""?".":ie+":";if(N(L))for(var we=0;we<L.length;we++)ie=L[we],Se=q+J(ie,we),ue+=U(ie,$,ne,Se,Ae);else if(we=b(L),typeof we=="function")for(L=we.call(L),we=0;!(ie=L.next()).done;)ie=ie.value,Se=q+J(ie,we++),ue+=U(ie,$,ne,Se,Ae);else if(Se==="object"){if(typeof L.then=="function")return U(fe(L),$,ne,ie,Ae);throw $=String(L),Error("Objects are not valid as a React child (found: "+($==="[object Object]"?"object with keys {"+Object.keys(L).join(", ")+"}":$)+"). If you meant to render a collection of children, use an array instead.")}return ue}function H(L,$,ne){if(L==null)return L;var ie=[],Ae=0;return U(L,ie,"","",function(Se){return $.call(ne,Se,Ae++)}),ie}function K(L){if(L._status===-1){var $=L._result;$=$(),$.then(function(ne){(L._status===0||L._status===-1)&&(L._status=1,L._result=ne)},function(ne){(L._status===0||L._status===-1)&&(L._status=2,L._result=ne)}),L._status===-1&&(L._status=0,L._result=$)}if(L._status===1)return L._result.default;throw L._result}var G=typeof reportError=="function"?reportError:function(L){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var $=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof L=="object"&&L!==null&&typeof L.message=="string"?String(L.message):String(L),error:L});if(!window.dispatchEvent($))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",L);return}console.error(L)},se={map:H,forEach:function(L,$,ne){H(L,function(){$.apply(this,arguments)},ne)},count:function(L){var $=0;return H(L,function(){$++}),$},toArray:function(L){return H(L,function($){return $})||[]},only:function(L){if(!pe(L))throw Error("React.Children.only expected to receive a single React element child.");return L}};return Fe.Activity=p,Fe.Children=se,Fe.Component=D,Fe.Fragment=o,Fe.Profiler=s,Fe.PureComponent=R,Fe.StrictMode=i,Fe.Suspense=v,Fe.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=F,Fe.__COMPILER_RUNTIME={__proto__:null,c:function(L){return F.H.useMemoCache(L)}},Fe.cache=function(L){return function(){return L.apply(null,arguments)}},Fe.cacheSignal=function(){return null},Fe.cloneElement=function(L,$,ne){if(L==null)throw Error("The argument must be a React element, but you passed "+L+".");var ie=x({},L.props),Ae=L.key;if($!=null)for(Se in $.key!==void 0&&(Ae=""+$.key),$)!O.call($,Se)||Se==="key"||Se==="__self"||Se==="__source"||Se==="ref"&&$.ref===void 0||(ie[Se]=$[Se]);var Se=arguments.length-2;if(Se===1)ie.children=ne;else if(1<Se){for(var ue=Array(Se),q=0;q<Se;q++)ue[q]=arguments[q+2];ie.children=ue}return I(L.type,Ae,ie)},Fe.createContext=function(L){return L={$$typeof:c,_currentValue:L,_currentValue2:L,_threadCount:0,Provider:null,Consumer:null},L.Provider=L,L.Consumer={$$typeof:u,_context:L},L},Fe.createElement=function(L,$,ne){var ie,Ae={},Se=null;if($!=null)for(ie in $.key!==void 0&&(Se=""+$.key),$)O.call($,ie)&&ie!=="key"&&ie!=="__self"&&ie!=="__source"&&(Ae[ie]=$[ie]);var ue=arguments.length-2;if(ue===1)Ae.children=ne;else if(1<ue){for(var q=Array(ue),we=0;we<ue;we++)q[we]=arguments[we+2];Ae.children=q}if(L&&L.defaultProps)for(ie in ue=L.defaultProps,ue)Ae[ie]===void 0&&(Ae[ie]=ue[ie]);return I(L,Se,Ae)},Fe.createRef=function(){return{current:null}},Fe.forwardRef=function(L){return{$$typeof:d,render:L}},Fe.isValidElement=pe,Fe.lazy=function(L){return{$$typeof:A,_payload:{_status:-1,_result:L},_init:K}},Fe.memo=function(L,$){return{$$typeof:m,type:L,compare:$===void 0?null:$}},Fe.startTransition=function(L){var $=F.T,ne={};F.T=ne;try{var ie=L(),Ae=F.S;Ae!==null&&Ae(ne,ie),typeof ie=="object"&&ie!==null&&typeof ie.then=="function"&&ie.then(j,G)}catch(Se){G(Se)}finally{$!==null&&ne.types!==null&&($.types=ne.types),F.T=$}},Fe.unstable_useCacheRefresh=function(){return F.H.useCacheRefresh()},Fe.use=function(L){return F.H.use(L)},Fe.useActionState=function(L,$,ne){return F.H.useActionState(L,$,ne)},Fe.useCallback=function(L,$){return F.H.useCallback(L,$)},Fe.useContext=function(L){return F.H.useContext(L)},Fe.useDebugValue=function(){},Fe.useDeferredValue=function(L,$){return F.H.useDeferredValue(L,$)},Fe.useEffect=function(L,$){return F.H.useEffect(L,$)},Fe.useEffectEvent=function(L){return F.H.useEffectEvent(L)},Fe.useId=function(){return F.H.useId()},Fe.useImperativeHandle=function(L,$,ne){return F.H.useImperativeHandle(L,$,ne)},Fe.useInsertionEffect=function(L,$){return F.H.useInsertionEffect(L,$)},Fe.useLayoutEffect=function(L,$){return F.H.useLayoutEffect(L,$)},Fe.useMemo=function(L,$){return F.H.useMemo(L,$)},Fe.useOptimistic=function(L,$){return F.H.useOptimistic(L,$)},Fe.useReducer=function(L,$,ne){return F.H.useReducer(L,$,ne)},Fe.useRef=function(L){return F.H.useRef(L)},Fe.useState=function(L){return F.H.useState(L)},Fe.useSyncExternalStore=function(L,$,ne){return F.H.useSyncExternalStore(L,$,ne)},Fe.useTransition=function(){return F.H.useTransition()},Fe.version="19.2.4",Fe}var Qv;function Zf(){return Qv||(Qv=1,b2.exports=Y4()),b2.exports}var y=Zf();const gt=El(y),li=W1({__proto__:null,default:gt},[y]);var Q4={};const Jf=Z4();function _t(t,...a){if(!Jf)return;const o=X4(t,...a);performance.mark(o);try{console.log(t,...a)}catch{console.log(o)}}function K4(t,...a){Jf&&console.warn(t,...a)}function X4(t,...a){return t.replace(/%[sfdO]/g,o=>{const i=a.shift();return o==="%O"&&i?JSON.stringify(i).replace(/"([^"]+)":/g,"$1:"):String(i)})}function Z4(){if(typeof window>"u")return(Q4.DEBUG||"").includes("nuqs");try{const t="nuqs-localStorage-test";if(typeof localStorage>"u")return!1;localStorage.setItem(t,t);const a=localStorage.getItem(t)===t;return localStorage.removeItem(t),a&&(localStorage.getItem("debug")||"").includes("nuqs")}catch{return!1}}const J4={303:"Multiple adapter contexts detected. This might happen in monorepos.",404:"nuqs requires an adapter to work with your framework.",409:"Multiple versions of the library are loaded. This may lead to unexpected behavior. Currently using `%s`, but `%s` (via the %s adapter) was about to load on top.",414:"Max safe URL length exceeded. Some browsers may not be able to accept this URL. Consider limiting the amount of state stored in the URL.",422:"Invalid options combination: `limitUrlUpdates: debounce` should be used in SSR scenarios, with `shallow: false`",429:"URL update rate-limited by the browser. Consider increasing `throttleMs` for key(s) `%s`. %O",500:"Empty search params cache. Search params can't be accessed in Layouts.",501:"Search params cache already populated. Have you called `parse` twice?"};function Sl(t){return`[nuqs] ${J4[t]} |
|
| 2 | + | See https://nuqs.dev/NUQS-${t}`}function W4(t){if(t.size===0)return"";const a=[];for(const[i,s]of t.entries()){const u=i.replace(/#/g,"%23").replace(/&/g,"%26").replace(/\+/g,"%2B").replace(/=/g,"%3D").replace(/\?/g,"%3F");a.push(`${u}=${eb(s)}`)}return"?"+a.join("&")}function eb(t){return t.replace(/%/g,"%25").replace(/\+/g,"%2B").replace(/ /g,"+").replace(/#/g,"%23").replace(/&/g,"%26").replace(/"/g,"%22").replace(/'/g,"%27").replace(/`/g,"%60").replace(/</g,"%3C").replace(/>/g,"%3E").replace(/[\x00-\x1F]/g,a=>encodeURIComponent(a))}const Xr=y.createContext({useAdapter(){throw new Error(Sl(404))}});Xr.displayName="NuqsAdapterContext";Jf&&typeof window<"u"&&(window.__NuqsAdapterContext&&window.__NuqsAdapterContext!==Xr&&console.error(Sl(303)),window.__NuqsAdapterContext=Xr);function tb(t){return({children:a,defaultOptions:o,processUrlSearchParams:i,...s})=>y.createElement(Xr.Provider,{...s,value:{useAdapter:t,defaultOptions:o,processUrlSearchParams:i}},a)}function nb(t){const a=y.useContext(Xr);if(!("useAdapter"in a))throw new Error(Sl(404));return a.useAdapter(t)}const ab=()=>y.useContext(Xr).defaultOptions,rb=()=>y.useContext(Xr).processUrlSearchParams;function ob(){if(typeof window>"u"||!window.GestureEvent)return 50;try{const t=navigator.userAgent?.match(/version\/([\d\.]+) safari/i);return parseFloat(t[1])>=17?120:320}catch{return 320}}function ib(t){return{method:"throttle",timeMs:t}}const hl=ib(ob());function lb(t){return t===null||Array.isArray(t)&&t.length===0}function sb(t,a,o){if(typeof t=="string")o.set(a,t);else{o.delete(a);for(const i of t)o.append(a,i);o.has(a)||o.set(a,"")}return o}function Wf(){const t=new Map;return{on(a,o){const i=t.get(a)||[];return i.push(o),t.set(a,i),()=>this.off(a,o)},off(a,o){const i=t.get(a);i&&t.set(a,i.filter(s=>s!==o))},emit(a,o){t.get(a)?.forEach(i=>i(o))}}}function vf(t,a,o){function i(){t(),o.removeEventListener("abort",u)}const s=setTimeout(i,a);function u(){clearTimeout(s),o.removeEventListener("abort",u)}o.addEventListener("abort",u)}function gf(){const t=Promise;if(Promise.hasOwnProperty("withResolvers"))return Promise.withResolvers();let a=()=>{},o=()=>{};return{promise:new t((i,s)=>{a=i,o=s}),resolve:a,reject:o}}function ub(t,a){let o=a;for(let i=t.length-1;i>=0;i--){const s=t[i];if(!s)continue;const u=o;o=()=>s(u)}o()}function yf(){return new URLSearchParams(location.search)}var ey=class{updateMap=new Map;options={history:"replace",scroll:!1,shallow:!0};timeMs=hl.timeMs;transitions=new Set;resolvers=null;controller=null;lastFlushedAt=0;resetQueueOnNextPush=!1;push({key:t,query:a,options:o},i=hl.timeMs){this.resetQueueOnNextPush&&(this.reset(),this.resetQueueOnNextPush=!1),_t("[nuqs gtq] Enqueueing %s=%s %O",t,a,o),this.updateMap.set(t,a),o.history==="push"&&(this.options.history="push"),o.scroll&&(this.options.scroll=!0),o.shallow===!1&&(this.options.shallow=!1),o.startTransition&&this.transitions.add(o.startTransition),(!Number.isFinite(this.timeMs)||i>this.timeMs)&&(this.timeMs=i)}getQueuedQuery(t){return this.updateMap.get(t)}getPendingPromise({getSearchParamsSnapshot:t=yf}){return this.resolvers?.promise??Promise.resolve(t())}flush({getSearchParamsSnapshot:t=yf,rateLimitFactor:a=1,...o},i){if(this.controller??=new AbortController,!Number.isFinite(this.timeMs))return _t("[nuqs gtq] Skipping flush due to throttleMs=Infinity"),Promise.resolve(t());if(this.resolvers)return this.resolvers.promise;this.resolvers=gf();const s=()=>{this.lastFlushedAt=performance.now();const[c,d]=this.applyPendingUpdates({...o,autoResetQueueOnUpdate:o.autoResetQueueOnUpdate??!0,getSearchParamsSnapshot:t},i);d===null?(this.resolvers.resolve(c),this.resetQueueOnNextPush=!0):this.resolvers.reject(c),this.resolvers=null};return vf(()=>{const c=performance.now()-this.lastFlushedAt,d=this.timeMs,v=a*Math.max(0,d-c);_t("[nuqs gtq] Scheduling flush in %f ms. Throttled at %f ms (x%f)",v,d,a),v===0?s():vf(s,v,this.controller.signal)},0,this.controller.signal),this.resolvers.promise}abort(){return this.controller?.abort(),this.controller=new AbortController,this.resolvers?.resolve(new URLSearchParams),this.resolvers=null,this.reset()}reset(){const t=Array.from(this.updateMap.keys());return _t("[nuqs gtq] Resetting queue %s",JSON.stringify(Object.fromEntries(this.updateMap))),this.updateMap.clear(),this.transitions.clear(),this.options={history:"replace",scroll:!1,shallow:!0},this.timeMs=hl.timeMs,t}applyPendingUpdates(t,a){const{updateUrl:o,getSearchParamsSnapshot:i}=t;let s=i();if(_t("[nuqs gtq] Applying %d pending update(s) on top of %s",this.updateMap.size,s.toString()),this.updateMap.size===0)return[s,null];const u=Array.from(this.updateMap.entries()),c={...this.options},d=Array.from(this.transitions);t.autoResetQueueOnUpdate&&this.reset(),_t("[nuqs gtq] Flushing queue %O with options %O",u,c);for(const[v,m]of u)m===null?s.delete(v):s=sb(m,v,s);a&&(s=a(s));try{return ub(d,()=>{o(s,c)}),[s,null]}catch(v){return console.error(Sl(429),u.map(([m])=>m).join(),v),[s,v]}}};const vu=new ey;function cb(t,a,o){const i=y.useCallback(()=>{const u=Object.fromEntries(t.map(c=>[c,o(c)]));return[JSON.stringify(u),u]},[t.join(","),o]),s=y.useRef(null);return s.current===null&&(s.current=i()),y.useSyncExternalStore(y.useCallback(u=>{const c=t.map(d=>a(d,u));return()=>c.forEach(d=>d())},[t.join(","),a]),()=>{const[u,c]=i();return s.current[0]===u?s.current[1]:(s.current=[u,c],c)},()=>s.current[1])}var fb=class{callback;resolvers=gf();controller=new AbortController;queuedValue=void 0;constructor(t){this.callback=t}abort(){this.controller.abort(),this.queuedValue=void 0}push(t,a){return this.queuedValue=t,this.controller.abort(),this.controller=new AbortController,vf(()=>{const o=this.resolvers;try{_t("[nuqs dq] Flushing debounce queue",t);const i=this.callback(t);_t("[nuqs dq] Reset debounce queue %O",this.queuedValue),this.queuedValue=void 0,this.resolvers=gf(),i.then(s=>o.resolve(s)).catch(s=>o.reject(s))}catch(i){this.queuedValue=void 0,o.reject(i)}},a,this.controller.signal),this.resolvers.promise}},db=class{throttleQueue;queues=new Map;queuedQuerySync=Wf();constructor(t=new ey){this.throttleQueue=t}useQueuedQueries(t){return cb(t,(a,o)=>this.queuedQuerySync.on(a,o),a=>this.getQueuedQuery(a))}push(t,a,o,i){if(!Number.isFinite(a)){const c=o.getSearchParamsSnapshot??yf;return Promise.resolve(c())}const s=t.key;if(!this.queues.has(s)){_t("[nuqs dqc] Creating debounce queue for `%s`",s);const c=new fb(d=>(this.throttleQueue.push(d),this.throttleQueue.flush(o,i).finally(()=>{this.queues.get(d.key)?.queuedValue===void 0&&(_t("[nuqs dqc] Cleaning up empty queue for `%s`",d.key),this.queues.delete(d.key)),this.queuedQuerySync.emit(d.key)})));this.queues.set(s,c)}_t("[nuqs dqc] Enqueueing debounce update %O",t);const u=this.queues.get(s).push(t,a);return this.queuedQuerySync.emit(s),u}abort(t){const a=this.queues.get(t);return a?(_t("[nuqs dqc] Aborting debounce queue %s=%s",t,a.queuedValue?.query),this.queues.delete(t),a.abort(),this.queuedQuerySync.emit(t),o=>(o.then(a.resolvers.resolve,a.resolvers.reject),o)):o=>o}abortAll(){for(const[t,a]of this.queues.entries())_t("[nuqs dqc] Aborting debounce queue %s=%s",t,a.queuedValue?.query),a.abort(),a.resolvers.resolve(new URLSearchParams),this.queuedQuerySync.emit(t);this.queues.clear()}getQueuedQuery(t){const a=this.queues.get(t)?.queuedValue?.query;return a!==void 0?a:this.throttleQueue.getQueuedQuery(t)}};const E2=new db(vu);function ty(t,a){return t===a?!0:t===null||a===null||typeof t=="string"||typeof a=="string"||t.length!==a.length?!1:t.every((o,i)=>o===a[i])}function Kv(t,a,o){return i=>{if(!(a.length===0||a.some(u=>!ty(i.getAll(u),t.getAll(u)))))return _t("[nuqs `%s`] no change, returning previous",a.join(","),i),i;const s=ny(t,a,o);return _t("[nuqs `%s`] subbed search params change\n from %O\n to %O",a.join(","),i,s),s}}function ny(t,a,o){if(a.length===0)return t;const i=o?new URLSearchParams(t):t;for(const s of t.keys())a.includes(s)||i.delete(s);return i}const hb="__nuqs__",Af=Wf();function pb(t){return function(o,i){const s=new URL(location.href);s.search=W4(o),_t("[nuqs react] Updating url: %s",s),t&&i.shallow===!1?(i.history==="push"?location.assign:location.replace).call(location,s):(i.history==="push"?history.pushState:history.replaceState).call(history,history.state,hb,s),Af.emit("update",o),i.scroll===!0&&window.scrollTo({top:0})}}const ay=y.createContext({fullPageNavigationOnShallowFalseUpdates:!1});function mb(t){const{fullPageNavigationOnShallowFalseUpdates:a}=y.useContext(ay),[o,i]=y.useState(()=>typeof location>"u"?new URLSearchParams:ny(new URLSearchParams(location.search),t,!1));return y.useEffect(()=>{const s=()=>{i(Kv(new URLSearchParams(location.search),t,!1))},u=c=>{i(Kv(c,t,!0))};return Af.on("update",u),window.addEventListener("popstate",s),()=>{Af.off("update",u),window.removeEventListener("popstate",s)}},[t.join("&")]),{searchParams:o,updateUrl:y.useMemo(()=>pb(a),[a])}}const vb=tb(mb);function gb({children:t,fullPageNavigationOnShallowFalseUpdates:a=!1,...o}){return y.createElement(ay.Provider,{value:{fullPageNavigationOnShallowFalseUpdates:a}},y.createElement(vb,{...o,children:t}))}var S2={exports:{}},rl={},x2={exports:{}},w2={};var Xv;function yb(){return Xv||(Xv=1,(function(t){function a(U,H){var K=U.length;U.push(H);e:for(;0<K;){var G=K-1>>>1,se=U[G];if(0<s(se,H))U[G]=H,U[K]=se,K=G;else break e}}function o(U){return U.length===0?null:U[0]}function i(U){if(U.length===0)return null;var H=U[0],K=U.pop();if(K!==H){U[0]=K;e:for(var G=0,se=U.length,L=se>>>1;G<L;){var $=2*(G+1)-1,ne=U[$],ie=$+1,Ae=U[ie];if(0>s(ne,K))ie<se&&0>s(Ae,ne)?(U[G]=Ae,U[ie]=K,G=ie):(U[G]=ne,U[$]=K,G=$);else if(ie<se&&0>s(Ae,K))U[G]=Ae,U[ie]=K,G=ie;else break e}}return H}function s(U,H){var K=U.sortIndex-H.sortIndex;return K!==0?K:U.id-H.id}if(t.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var u=performance;t.unstable_now=function(){return u.now()}}else{var c=Date,d=c.now();t.unstable_now=function(){return c.now()-d}}var v=[],m=[],A=1,p=null,C=3,b=!1,S=!1,x=!1,w=!1,D=typeof setTimeout=="function"?setTimeout:null,T=typeof clearTimeout=="function"?clearTimeout:null,R=typeof setImmediate<"u"?setImmediate:null;function _(U){for(var H=o(m);H!==null;){if(H.callback===null)i(m);else if(H.startTime<=U)i(m),H.sortIndex=H.expirationTime,a(v,H);else break;H=o(m)}}function N(U){if(x=!1,_(U),!S)if(o(v)!==null)S=!0,j||(j=!0,ce());else{var H=o(m);H!==null&&fe(N,H.startTime-U)}}var j=!1,F=-1,O=5,I=-1;function re(){return w?!0:!(t.unstable_now()-I<O)}function pe(){if(w=!1,j){var U=t.unstable_now();I=U;var H=!0;try{e:{S=!1,x&&(x=!1,T(F),F=-1),b=!0;var K=C;try{t:{for(_(U),p=o(v);p!==null&&!(p.expirationTime>U&&re());){var G=p.callback;if(typeof G=="function"){p.callback=null,C=p.priorityLevel;var se=G(p.expirationTime<=U);if(U=t.unstable_now(),typeof se=="function"){p.callback=se,_(U),H=!0;break t}p===o(v)&&i(v),_(U)}else i(v);p=o(v)}if(p!==null)H=!0;else{var L=o(m);L!==null&&fe(N,L.startTime-U),H=!1}}break e}finally{p=null,C=K,b=!1}H=void 0}}finally{H?ce():j=!1}}}var ce;if(typeof R=="function")ce=function(){R(pe)};else if(typeof MessageChannel<"u"){var de=new MessageChannel,J=de.port2;de.port1.onmessage=pe,ce=function(){J.postMessage(null)}}else ce=function(){D(pe,0)};function fe(U,H){F=D(function(){U(t.unstable_now())},H)}t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(U){U.callback=null},t.unstable_forceFrameRate=function(U){0>U||125<U?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):O=0<U?Math.floor(1e3/U):5},t.unstable_getCurrentPriorityLevel=function(){return C},t.unstable_next=function(U){switch(C){case 1:case 2:case 3:var H=3;break;default:H=C}var K=C;C=H;try{return U()}finally{C=K}},t.unstable_requestPaint=function(){w=!0},t.unstable_runWithPriority=function(U,H){switch(U){case 1:case 2:case 3:case 4:case 5:break;default:U=3}var K=C;C=U;try{return H()}finally{C=K}},t.unstable_scheduleCallback=function(U,H,K){var G=t.unstable_now();switch(typeof K=="object"&&K!==null?(K=K.delay,K=typeof K=="number"&&0<K?G+K:G):K=G,U){case 1:var se=-1;break;case 2:se=250;break;case 5:se=1073741823;break;case 4:se=1e4;break;default:se=5e3}return se=K+se,U={id:A++,callback:H,priorityLevel:U,startTime:K,expirationTime:se,sortIndex:-1},K>G?(U.sortIndex=K,a(m,U),o(v)===null&&U===o(m)&&(x?(T(F),F=-1):x=!0,fe(N,K-G))):(U.sortIndex=se,a(v,U),S||b||(S=!0,j||(j=!0,ce()))),U},t.unstable_shouldYield=re,t.unstable_wrapCallback=function(U){var H=C;return function(){var K=C;C=H;try{return U.apply(this,arguments)}finally{C=K}}}})(w2)),w2}var Zv;function Ab(){return Zv||(Zv=1,x2.exports=yb()),x2.exports}var _2={exports:{}},an={};var Jv;function Cb(){if(Jv)return an;Jv=1;var t=Zf();function a(v){var m="https://react.dev/errors/"+v;if(1<arguments.length){m+="?args[]="+encodeURIComponent(arguments[1]);for(var A=2;A<arguments.length;A++)m+="&args[]="+encodeURIComponent(arguments[A])}return"Minified React error #"+v+"; visit "+m+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function o(){}var i={d:{f:o,r:function(){throw Error(a(522))},D:o,C:o,L:o,m:o,X:o,S:o,M:o},p:0,findDOMNode:null},s=Symbol.for("react.portal");function u(v,m,A){var p=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:s,key:p==null?null:""+p,children:v,containerInfo:m,implementation:A}}var c=t.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function d(v,m){if(v==="font")return"";if(typeof m=="string")return m==="use-credentials"?m:""}return an.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=i,an.createPortal=function(v,m){var A=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!m||m.nodeType!==1&&m.nodeType!==9&&m.nodeType!==11)throw Error(a(299));return u(v,m,null,A)},an.flushSync=function(v){var m=c.T,A=i.p;try{if(c.T=null,i.p=2,v)return v()}finally{c.T=m,i.p=A,i.d.f()}},an.preconnect=function(v,m){typeof v=="string"&&(m?(m=m.crossOrigin,m=typeof m=="string"?m==="use-credentials"?m:"":void 0):m=null,i.d.C(v,m))},an.prefetchDNS=function(v){typeof v=="string"&&i.d.D(v)},an.preinit=function(v,m){if(typeof v=="string"&&m&&typeof m.as=="string"){var A=m.as,p=d(A,m.crossOrigin),C=typeof m.integrity=="string"?m.integrity:void 0,b=typeof m.fetchPriority=="string"?m.fetchPriority:void 0;A==="style"?i.d.S(v,typeof m.precedence=="string"?m.precedence:void 0,{crossOrigin:p,integrity:C,fetchPriority:b}):A==="script"&&i.d.X(v,{crossOrigin:p,integrity:C,fetchPriority:b,nonce:typeof m.nonce=="string"?m.nonce:void 0})}},an.preinitModule=function(v,m){if(typeof v=="string")if(typeof m=="object"&&m!==null){if(m.as==null||m.as==="script"){var A=d(m.as,m.crossOrigin);i.d.M(v,{crossOrigin:A,integrity:typeof m.integrity=="string"?m.integrity:void 0,nonce:typeof m.nonce=="string"?m.nonce:void 0})}}else m==null&&i.d.M(v)},an.preload=function(v,m){if(typeof v=="string"&&typeof m=="object"&&m!==null&&typeof m.as=="string"){var A=m.as,p=d(A,m.crossOrigin);i.d.L(v,A,{crossOrigin:p,integrity:typeof m.integrity=="string"?m.integrity:void 0,nonce:typeof m.nonce=="string"?m.nonce:void 0,type:typeof m.type=="string"?m.type:void 0,fetchPriority:typeof m.fetchPriority=="string"?m.fetchPriority:void 0,referrerPolicy:typeof m.referrerPolicy=="string"?m.referrerPolicy:void 0,imageSrcSet:typeof m.imageSrcSet=="string"?m.imageSrcSet:void 0,imageSizes:typeof m.imageSizes=="string"?m.imageSizes:void 0,media:typeof m.media=="string"?m.media:void 0})}},an.preloadModule=function(v,m){if(typeof v=="string")if(m){var A=d(m.as,m.crossOrigin);i.d.m(v,{as:typeof m.as=="string"&&m.as!=="script"?m.as:void 0,crossOrigin:A,integrity:typeof m.integrity=="string"?m.integrity:void 0})}else i.d.m(v)},an.requestFormReset=function(v){i.d.r(v)},an.unstable_batchedUpdates=function(v,m){return v(m)},an.useFormState=function(v,m,A){return c.H.useFormState(v,m,A)},an.useFormStatus=function(){return c.H.useHostTransitionStatus()},an.version="19.2.4",an}var Wv;function ry(){if(Wv)return _2.exports;Wv=1;function t(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(a){console.error(a)}}return t(),_2.exports=Cb(),_2.exports}var eg;function bb(){if(eg)return rl;eg=1;var t=Ab(),a=Zf(),o=ry();function i(e){var n="https://react.dev/errors/"+e;if(1<arguments.length){n+="?args[]="+encodeURIComponent(arguments[1]);for(var r=2;r<arguments.length;r++)n+="&args[]="+encodeURIComponent(arguments[r])}return"Minified React error #"+e+"; visit "+n+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function s(e){return!(!e||e.nodeType!==1&&e.nodeType!==9&&e.nodeType!==11)}function u(e){var n=e,r=e;if(e.alternate)for(;n.return;)n=n.return;else{e=n;do n=e,(n.flags&4098)!==0&&(r=n.return),e=n.return;while(e)}return n.tag===3?r:null}function c(e){if(e.tag===13){var n=e.memoizedState;if(n===null&&(e=e.alternate,e!==null&&(n=e.memoizedState)),n!==null)return n.dehydrated}return null}function d(e){if(e.tag===31){var n=e.memoizedState;if(n===null&&(e=e.alternate,e!==null&&(n=e.memoizedState)),n!==null)return n.dehydrated}return null}function v(e){if(u(e)!==e)throw Error(i(188))}function m(e){var n=e.alternate;if(!n){if(n=u(e),n===null)throw Error(i(188));return n!==e?null:e}for(var r=e,l=n;;){var f=r.return;if(f===null)break;var h=f.alternate;if(h===null){if(l=f.return,l!==null){r=l;continue}break}if(f.child===h.child){for(h=f.child;h;){if(h===r)return v(f),e;if(h===l)return v(f),n;h=h.sibling}throw Error(i(188))}if(r.return!==l.return)r=f,l=h;else{for(var E=!1,M=f.child;M;){if(M===r){E=!0,r=f,l=h;break}if(M===l){E=!0,l=f,r=h;break}M=M.sibling}if(!E){for(M=h.child;M;){if(M===r){E=!0,r=h,l=f;break}if(M===l){E=!0,l=h,r=f;break}M=M.sibling}if(!E)throw Error(i(189))}}if(r.alternate!==l)throw Error(i(190))}if(r.tag!==3)throw Error(i(188));return r.stateNode.current===r?e:n}function A(e){var n=e.tag;if(n===5||n===26||n===27||n===6)return e;for(e=e.child;e!==null;){if(n=A(e),n!==null)return n;e=e.sibling}return null}var p=Object.assign,C=Symbol.for("react.element"),b=Symbol.for("react.transitional.element"),S=Symbol.for("react.portal"),x=Symbol.for("react.fragment"),w=Symbol.for("react.strict_mode"),D=Symbol.for("react.profiler"),T=Symbol.for("react.consumer"),R=Symbol.for("react.context"),_=Symbol.for("react.forward_ref"),N=Symbol.for("react.suspense"),j=Symbol.for("react.suspense_list"),F=Symbol.for("react.memo"),O=Symbol.for("react.lazy"),I=Symbol.for("react.activity"),re=Symbol.for("react.memo_cache_sentinel"),pe=Symbol.iterator;function ce(e){return e===null||typeof e!="object"?null:(e=pe&&e[pe]||e["@@iterator"],typeof e=="function"?e:null)}var de=Symbol.for("react.client.reference");function J(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===de?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case x:return"Fragment";case D:return"Profiler";case w:return"StrictMode";case N:return"Suspense";case j:return"SuspenseList";case I:return"Activity"}if(typeof e=="object")switch(e.$$typeof){case S:return"Portal";case R:return e.displayName||"Context";case T:return(e._context.displayName||"Context")+".Consumer";case _:var n=e.render;return e=e.displayName,e||(e=n.displayName||n.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case F:return n=e.displayName||null,n!==null?n:J(e.type)||"Memo";case O:n=e._payload,e=e._init;try{return J(e(n))}catch{}}return null}var fe=Array.isArray,U=a.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,H=o.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,K={pending:!1,data:null,method:null,action:null},G=[],se=-1;function L(e){return{current:e}}function $(e){0>se||(e.current=G[se],G[se]=null,se--)}function ne(e,n){se++,G[se]=e.current,e.current=n}var ie=L(null),Ae=L(null),Se=L(null),ue=L(null);function q(e,n){switch(ne(Se,n),ne(Ae,e),ne(ie,null),n.nodeType){case 9:case 11:e=(e=n.documentElement)&&(e=e.namespaceURI)?pv(e):0;break;default:if(e=n.tagName,n=n.namespaceURI)n=pv(n),e=mv(n,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}$(ie),ne(ie,e)}function we(){$(ie),$(Ae),$(Se)}function lt(e){e.memoizedState!==null&&ne(ue,e);var n=ie.current,r=mv(n,e.type);n!==r&&(ne(Ae,e),ne(ie,r))}function Xe(e){Ae.current===e&&($(ie),$(Ae)),ue.current===e&&($(ue),Wi._currentValue=K)}var W,te;function pt(e){if(W===void 0)try{throw Error()}catch(r){var n=r.stack.trim().match(/\n( *(at )?)/);W=n&&n[1]||"",te=-1<r.stack.indexOf(` |
|
| 3 | + | at`)?" (<anonymous>)":-1<r.stack.indexOf("@")?"@unknown:0:0":""}return` |
|
| 4 | + | `+W+e+te}var Ze=!1;function At(e,n){if(!e||Ze)return"";Ze=!0;var r=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var l={DetermineComponentFrameRoot:function(){try{if(n){var le=function(){throw Error()};if(Object.defineProperty(le.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(le,[])}catch(ee){var Z=ee}Reflect.construct(e,[],le)}else{try{le.call()}catch(ee){Z=ee}e.call(le.prototype)}}else{try{throw Error()}catch(ee){Z=ee}(le=e())&&typeof le.catch=="function"&&le.catch(function(){})}}catch(ee){if(ee&&Z&&typeof ee.stack=="string")return[ee.stack,Z.stack]}return[null,null]}};l.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var f=Object.getOwnPropertyDescriptor(l.DetermineComponentFrameRoot,"name");f&&f.configurable&&Object.defineProperty(l.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var h=l.DetermineComponentFrameRoot(),E=h[0],M=h[1];if(E&&M){var k=E.split(` |
|
| 5 | + | `),Q=M.split(` |
|
| 6 | + | `);for(f=l=0;l<k.length&&!k[l].includes("DetermineComponentFrameRoot");)l++;for(;f<Q.length&&!Q[f].includes("DetermineComponentFrameRoot");)f++;if(l===k.length||f===Q.length)for(l=k.length-1,f=Q.length-1;1<=l&&0<=f&&k[l]!==Q[f];)f--;for(;1<=l&&0<=f;l--,f--)if(k[l]!==Q[f]){if(l!==1||f!==1)do if(l--,f--,0>f||k[l]!==Q[f]){var ae=` |
|
| 7 | + | `+k[l].replace(" at new "," at ");return e.displayName&&ae.includes("<anonymous>")&&(ae=ae.replace("<anonymous>",e.displayName)),ae}while(1<=l&&0<=f);break}}}finally{Ze=!1,Error.prepareStackTrace=r}return(r=e?e.displayName||e.name:"")?pt(r):""}function Je(e,n){switch(e.tag){case 26:case 27:case 5:return pt(e.type);case 16:return pt("Lazy");case 13:return e.child!==n&&n!==null?pt("Suspense Fallback"):pt("Suspense");case 19:return pt("SuspenseList");case 0:case 15:return At(e.type,!1);case 11:return At(e.type.render,!1);case 1:return At(e.type,!0);case 31:return pt("Activity");default:return""}}function en(e){try{var n="",r=null;do n+=Je(e,r),r=e,e=e.return;while(e);return n}catch(l){return` |
|
| 8 | + | Error generating stack: `+l.message+` |
|
| 9 | + | `+l.stack}}var yn=Object.prototype.hasOwnProperty,On=t.unstable_scheduleCallback,la=t.unstable_cancelCallback,Nn=t.unstable_shouldYield,Ue=t.unstable_requestPaint,kt=t.unstable_now,Kn=t.unstable_getCurrentPriorityLevel,ye=t.unstable_ImmediatePriority,at=t.unstable_UserBlockingPriority,ve=t.unstable_NormalPriority,je=t.unstable_LowPriority,He=t.unstable_IdlePriority,xt=t.log,rt=t.unstable_setDisableYieldValue,zt=null,mt=null;function qt(e){if(typeof xt=="function"&&rt(e),mt&&typeof mt.setStrictMode=="function")try{mt.setStrictMode(zt,e)}catch{}}var tn=Math.clz32?Math.clz32:dc,kl=Math.log,zl=Math.LN2;function dc(e){return e>>>=0,e===0?32:31-(kl(e)/zl|0)|0}var Tr=256,Ea=262144,Mr=4194304;function Xn(e){var n=e&42;if(n!==0)return n;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function lo(e,n,r){var l=e.pendingLanes;if(l===0)return 0;var f=0,h=e.suspendedLanes,E=e.pingedLanes;e=e.warmLanes;var M=l&134217727;return M!==0?(l=M&~h,l!==0?f=Xn(l):(E&=M,E!==0?f=Xn(E):r||(r=M&~e,r!==0&&(f=Xn(r))))):(M=l&~h,M!==0?f=Xn(M):E!==0?f=Xn(E):r||(r=l&~e,r!==0&&(f=Xn(r)))),f===0?0:n!==0&&n!==f&&(n&h)===0&&(h=f&-f,r=n&-n,h>=r||h===32&&(r&4194048)!==0)?n:f}function Ya(e,n){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&n)===0}function hc(e,n){switch(e){case 1:case 2:case 4:case 8:case 64:return n+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return n+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function mi(){var e=Mr;return Mr<<=1,(Mr&62914560)===0&&(Mr=4194304),e}function Qa(e){for(var n=[],r=0;31>r;r++)n.push(e);return n}function sa(e,n){e.pendingLanes|=n,n!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Ul(e,n,r,l,f,h){var E=e.pendingLanes;e.pendingLanes=r,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=r,e.entangledLanes&=r,e.errorRecoveryDisabledLanes&=r,e.shellSuspendCounter=0;var M=e.entanglements,k=e.expirationTimes,Q=e.hiddenUpdates;for(r=E&~r;0<r;){var ae=31-tn(r),le=1<<ae;M[ae]=0,k[ae]=-1;var Z=Q[ae];if(Z!==null)for(Q[ae]=null,ae=0;ae<Z.length;ae++){var ee=Z[ae];ee!==null&&(ee.lane&=-536870913)}r&=~le}l!==0&&Pl(e,l,0),h!==0&&f===0&&e.tag!==0&&(e.suspendedLanes|=h&~(E&~n))}function Pl(e,n,r){e.pendingLanes|=n,e.suspendedLanes&=~n;var l=31-tn(n);e.entangledLanes|=n,e.entanglements[l]=e.entanglements[l]|1073741824|r&261930}function Il(e,n){var r=e.entangledLanes|=n;for(e=e.entanglements;r;){var l=31-tn(r),f=1<<l;f&n|e[l]&n&&(e[l]|=n),r&=~f}}function z(e,n){var r=n&-n;return r=(r&42)!==0?1:B(r),(r&(e.suspendedLanes|n))!==0?0:r}function B(e){switch(e){case 2:e=1;break;case 8:e=4;break;case 32:e=16;break;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:e=128;break;case 268435456:e=134217728;break;default:e=0}return e}function X(e){return e&=-e,2<e?8<e?(e&134217727)!==0?32:268435456:8:2}function he(){var e=H.p;return e!==0?e:(e=window.event,e===void 0?32:Uv(e.type))}function ge(e,n){var r=H.p;try{return H.p=e,n()}finally{H.p=r}}var _e=Math.random().toString(36).slice(2),Ce="__reactFiber$"+_e,be="__reactProps$"+_e,Te="__reactContainer$"+_e,Ee="__reactEvents$"+_e,Ne="__reactListeners$"+_e,De="__reactHandles$"+_e,We="__reactResources$"+_e,Be="__reactMarker$"+_e;function dt(e){delete e[Ce],delete e[be],delete e[Ee],delete e[Ne],delete e[De]}function Ct(e){var n=e[Ce];if(n)return n;for(var r=e.parentNode;r;){if(n=r[Te]||r[Ce]){if(r=n.alternate,n.child!==null||r!==null&&r.child!==null)for(e=Ev(e);e!==null;){if(r=e[Ce])return r;e=Ev(e)}return n}e=r,r=e.parentNode}return null}function Rt(e){if(e=e[Ce]||e[Te]){var n=e.tag;if(n===5||n===6||n===13||n===31||n===26||n===27||n===3)return e}return null}function Ke(e){var n=e.tag;if(n===5||n===26||n===27||n===6)return e.stateNode;throw Error(i(33))}function Ut(e){var n=e[We];return n||(n=e[We]={hoistableStyles:new Map,hoistableScripts:new Map}),n}function vt(e){e[Be]=!0}var Ka=new Set,Zn={};function Gt(e,n){ua(e,n),ua(e+"Capture",n)}function ua(e,n){for(Zn[e]=n,e=0;e<n.length;e++)Ka.add(n[e])}var Dr=RegExp("^[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$"),ca={},Or={};function so(e){return yn.call(Or,e)?!0:yn.call(ca,e)?!1:Dr.test(e)?Or[e]=!0:(ca[e]=!0,!1)}function $e(e,n,r){if(so(n))if(r===null)e.removeAttribute(n);else{switch(typeof r){case"undefined":case"function":case"symbol":e.removeAttribute(n);return;case"boolean":var l=n.toLowerCase().slice(0,5);if(l!=="data-"&&l!=="aria-"){e.removeAttribute(n);return}}e.setAttribute(n,""+r)}}function Nt(e,n,r){if(r===null)e.removeAttribute(n);else{switch(typeof r){case"undefined":case"function":case"symbol":case"boolean":e.removeAttribute(n);return}e.setAttribute(n,""+r)}}function nn(e,n,r,l){if(l===null)e.removeAttribute(r);else{switch(typeof l){case"undefined":case"function":case"symbol":case"boolean":e.removeAttribute(r);return}e.setAttributeNS(n,r,""+l)}}function Pt(e){switch(typeof e){case"bigint":case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function bt(e){var n=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(n==="checkbox"||n==="radio")}function uo(e,n,r){var l=Object.getOwnPropertyDescriptor(e.constructor.prototype,n);if(!e.hasOwnProperty(n)&&typeof l<"u"&&typeof l.get=="function"&&typeof l.set=="function"){var f=l.get,h=l.set;return Object.defineProperty(e,n,{configurable:!0,get:function(){return f.call(this)},set:function(E){r=""+E,h.call(this,E)}}),Object.defineProperty(e,n,{enumerable:l.enumerable}),{getValue:function(){return r},setValue:function(E){r=""+E},stopTracking:function(){e._valueTracker=null,delete e[n]}}}}function co(e){if(!e._valueTracker){var n=bt(e)?"checked":"value";e._valueTracker=uo(e,n,""+e[n])}}function Hl(e){if(!e)return!1;var n=e._valueTracker;if(!n)return!0;var r=n.getValue(),l="";return e&&(l=bt(e)?e.checked?"true":"false":e.value),e=l,e!==r?(n.setValue(e),!0):!1}function Bl(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var z6=/[\n"\\]/g;function Ln(e){return e.replace(z6,function(n){return"\\"+n.charCodeAt(0).toString(16)+" "})}function pc(e,n,r,l,f,h,E,M){e.name="",E!=null&&typeof E!="function"&&typeof E!="symbol"&&typeof E!="boolean"?e.type=E:e.removeAttribute("type"),n!=null?E==="number"?(n===0&&e.value===""||e.value!=n)&&(e.value=""+Pt(n)):e.value!==""+Pt(n)&&(e.value=""+Pt(n)):E!=="submit"&&E!=="reset"||e.removeAttribute("value"),n!=null?mc(e,E,Pt(n)):r!=null?mc(e,E,Pt(r)):l!=null&&e.removeAttribute("value"),f==null&&h!=null&&(e.defaultChecked=!!h),f!=null&&(e.checked=f&&typeof f!="function"&&typeof f!="symbol"),M!=null&&typeof M!="function"&&typeof M!="symbol"&&typeof M!="boolean"?e.name=""+Pt(M):e.removeAttribute("name")}function sh(e,n,r,l,f,h,E,M){if(h!=null&&typeof h!="function"&&typeof h!="symbol"&&typeof h!="boolean"&&(e.type=h),n!=null||r!=null){if(!(h!=="submit"&&h!=="reset"||n!=null)){co(e);return}r=r!=null?""+Pt(r):"",n=n!=null?""+Pt(n):r,M||n===e.value||(e.value=n),e.defaultValue=n}l=l??f,l=typeof l!="function"&&typeof l!="symbol"&&!!l,e.checked=M?e.checked:!!l,e.defaultChecked=!!l,E!=null&&typeof E!="function"&&typeof E!="symbol"&&typeof E!="boolean"&&(e.name=E),co(e)}function mc(e,n,r){n==="number"&&Bl(e.ownerDocument)===e||e.defaultValue===""+r||(e.defaultValue=""+r)}function fo(e,n,r,l){if(e=e.options,n){n={};for(var f=0;f<r.length;f++)n["$"+r[f]]=!0;for(r=0;r<e.length;r++)f=n.hasOwnProperty("$"+e[r].value),e[r].selected!==f&&(e[r].selected=f),f&&l&&(e[r].defaultSelected=!0)}else{for(r=""+Pt(r),n=null,f=0;f<e.length;f++){if(e[f].value===r){e[f].selected=!0,l&&(e[f].defaultSelected=!0);return}n!==null||e[f].disabled||(n=e[f])}n!==null&&(n.selected=!0)}}function uh(e,n,r){if(n!=null&&(n=""+Pt(n),n!==e.value&&(e.value=n),r==null)){e.defaultValue!==n&&(e.defaultValue=n);return}e.defaultValue=r!=null?""+Pt(r):""}function ch(e,n,r,l){if(n==null){if(l!=null){if(r!=null)throw Error(i(92));if(fe(l)){if(1<l.length)throw Error(i(93));l=l[0]}r=l}r==null&&(r=""),n=r}r=Pt(n),e.defaultValue=r,l=e.textContent,l===r&&l!==""&&l!==null&&(e.value=l),co(e)}function ho(e,n){if(n){var r=e.firstChild;if(r&&r===e.lastChild&&r.nodeType===3){r.nodeValue=n;return}}e.textContent=n}var U6=new Set("animationIterationCount aspectRatio borderImageOutset borderImageSlice borderImageWidth boxFlex boxFlexGroup boxOrdinalGroup columnCount columns flex flexGrow flexPositive flexShrink flexNegative flexOrder gridArea gridRow gridRowEnd gridRowSpan gridRowStart gridColumn gridColumnEnd gridColumnSpan gridColumnStart fontWeight lineClamp lineHeight opacity order orphans scale tabSize widows zIndex zoom fillOpacity floodOpacity stopOpacity strokeDasharray strokeDashoffset strokeMiterlimit strokeOpacity strokeWidth MozAnimationIterationCount MozBoxFlex MozBoxFlexGroup MozLineClamp msAnimationIterationCount msFlex msZoom msFlexGrow msFlexNegative msFlexOrder msFlexPositive msFlexShrink msGridColumn msGridColumnSpan msGridRow msGridRowSpan WebkitAnimationIterationCount WebkitBoxFlex WebKitBoxFlexGroup WebkitBoxOrdinalGroup WebkitColumnCount WebkitColumns WebkitFlex WebkitFlexGrow WebkitFlexPositive WebkitFlexShrink WebkitLineClamp".split(" "));function fh(e,n,r){var l=n.indexOf("--")===0;r==null||typeof r=="boolean"||r===""?l?e.setProperty(n,""):n==="float"?e.cssFloat="":e[n]="":l?e.setProperty(n,r):typeof r!="number"||r===0||U6.has(n)?n==="float"?e.cssFloat=r:e[n]=(""+r).trim():e[n]=r+"px"}function dh(e,n,r){if(n!=null&&typeof n!="object")throw Error(i(62));if(e=e.style,r!=null){for(var l in r)!r.hasOwnProperty(l)||n!=null&&n.hasOwnProperty(l)||(l.indexOf("--")===0?e.setProperty(l,""):l==="float"?e.cssFloat="":e[l]="");for(var f in n)l=n[f],n.hasOwnProperty(f)&&r[f]!==l&&fh(e,f,l)}else for(var h in n)n.hasOwnProperty(h)&&fh(e,h,n[h])}function vc(e){if(e.indexOf("-")===-1)return!1;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var P6=new Map([["acceptCharset","accept-charset"],["htmlFor","for"],["httpEquiv","http-equiv"],["crossOrigin","crossorigin"],["accentHeight","accent-height"],["alignmentBaseline","alignment-baseline"],["arabicForm","arabic-form"],["baselineShift","baseline-shift"],["capHeight","cap-height"],["clipPath","clip-path"],["clipRule","clip-rule"],["colorInterpolation","color-interpolation"],["colorInterpolationFilters","color-interpolation-filters"],["colorProfile","color-profile"],["colorRendering","color-rendering"],["dominantBaseline","dominant-baseline"],["enableBackground","enable-background"],["fillOpacity","fill-opacity"],["fillRule","fill-rule"],["floodColor","flood-color"],["floodOpacity","flood-opacity"],["fontFamily","font-family"],["fontSize","font-size"],["fontSizeAdjust","font-size-adjust"],["fontStretch","font-stretch"],["fontStyle","font-style"],["fontVariant","font-variant"],["fontWeight","font-weight"],["glyphName","glyph-name"],["glyphOrientationHorizontal","glyph-orientation-horizontal"],["glyphOrientationVertical","glyph-orientation-vertical"],["horizAdvX","horiz-adv-x"],["horizOriginX","horiz-origin-x"],["imageRendering","image-rendering"],["letterSpacing","letter-spacing"],["lightingColor","lighting-color"],["markerEnd","marker-end"],["markerMid","marker-mid"],["markerStart","marker-start"],["overlinePosition","overline-position"],["overlineThickness","overline-thickness"],["paintOrder","paint-order"],["panose-1","panose-1"],["pointerEvents","pointer-events"],["renderingIntent","rendering-intent"],["shapeRendering","shape-rendering"],["stopColor","stop-color"],["stopOpacity","stop-opacity"],["strikethroughPosition","strikethrough-position"],["strikethroughThickness","strikethrough-thickness"],["strokeDasharray","stroke-dasharray"],["strokeDashoffset","stroke-dashoffset"],["strokeLinecap","stroke-linecap"],["strokeLinejoin","stroke-linejoin"],["strokeMiterlimit","stroke-miterlimit"],["strokeOpacity","stroke-opacity"],["strokeWidth","stroke-width"],["textAnchor","text-anchor"],["textDecoration","text-decoration"],["textRendering","text-rendering"],["transformOrigin","transform-origin"],["underlinePosition","underline-position"],["underlineThickness","underline-thickness"],["unicodeBidi","unicode-bidi"],["unicodeRange","unicode-range"],["unitsPerEm","units-per-em"],["vAlphabetic","v-alphabetic"],["vHanging","v-hanging"],["vIdeographic","v-ideographic"],["vMathematical","v-mathematical"],["vectorEffect","vector-effect"],["vertAdvY","vert-adv-y"],["vertOriginX","vert-origin-x"],["vertOriginY","vert-origin-y"],["wordSpacing","word-spacing"],["writingMode","writing-mode"],["xmlnsXlink","xmlns:xlink"],["xHeight","x-height"]]),I6=/^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*:/i;function $l(e){return I6.test(""+e)?"javascript:throw new Error('React has blocked a javascript: URL as a security precaution.')":e}function Sa(){}var gc=null;function yc(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var po=null,mo=null;function hh(e){var n=Rt(e);if(n&&(e=n.stateNode)){var r=e[be]||null;e:switch(e=n.stateNode,n.type){case"input":if(pc(e,r.value,r.defaultValue,r.defaultValue,r.checked,r.defaultChecked,r.type,r.name),n=r.name,r.type==="radio"&&n!=null){for(r=e;r.parentNode;)r=r.parentNode;for(r=r.querySelectorAll('input[name="'+Ln(""+n)+'"][type="radio"]'),n=0;n<r.length;n++){var l=r[n];if(l!==e&&l.form===e.form){var f=l[be]||null;if(!f)throw Error(i(90));pc(l,f.value,f.defaultValue,f.defaultValue,f.checked,f.defaultChecked,f.type,f.name)}}for(n=0;n<r.length;n++)l=r[n],l.form===e.form&&Hl(l)}break e;case"textarea":uh(e,r.value,r.defaultValue);break e;case"select":n=r.value,n!=null&&fo(e,!!r.multiple,n,!1)}}}var Ac=!1;function ph(e,n,r){if(Ac)return e(n,r);Ac=!0;try{var l=e(n);return l}finally{if(Ac=!1,(po!==null||mo!==null)&&(Ds(),po&&(n=po,e=mo,mo=po=null,hh(n),e)))for(n=0;n<e.length;n++)hh(e[n])}}function vi(e,n){var r=e.stateNode;if(r===null)return null;var l=r[be]||null;if(l===null)return null;r=l[n];e:switch(n){case"onClick":case"onClickCapture":case"onDoubleClick":case"onDoubleClickCapture":case"onMouseDown":case"onMouseDownCapture":case"onMouseMove":case"onMouseMoveCapture":case"onMouseUp":case"onMouseUpCapture":case"onMouseEnter":(l=!l.disabled)||(e=e.type,l=!(e==="button"||e==="input"||e==="select"||e==="textarea")),e=!l;break e;default:e=!1}if(e)return null;if(r&&typeof r!="function")throw Error(i(231,n,typeof r));return r}var xa=!(typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Cc=!1;if(xa)try{var gi={};Object.defineProperty(gi,"passive",{get:function(){Cc=!0}}),window.addEventListener("test",gi,gi),window.removeEventListener("test",gi,gi)}catch{Cc=!1}var Xa=null,bc=null,Vl=null;function mh(){if(Vl)return Vl;var e,n=bc,r=n.length,l,f="value"in Xa?Xa.value:Xa.textContent,h=f.length;for(e=0;e<r&&n[e]===f[e];e++);var E=r-e;for(l=1;l<=E&&n[r-l]===f[h-l];l++);return Vl=f.slice(e,1<l?1-l:void 0)}function ql(e){var n=e.keyCode;return"charCode"in e?(e=e.charCode,e===0&&n===13&&(e=13)):e=n,e===10&&(e=13),32<=e||e===13?e:0}function Gl(){return!0}function vh(){return!1}function fn(e){function n(r,l,f,h,E){this._reactName=r,this._targetInst=f,this.type=l,this.nativeEvent=h,this.target=E,this.currentTarget=null;for(var M in e)e.hasOwnProperty(M)&&(r=e[M],this[M]=r?r(h):h[M]);return this.isDefaultPrevented=(h.defaultPrevented!=null?h.defaultPrevented:h.returnValue===!1)?Gl:vh,this.isPropagationStopped=vh,this}return p(n.prototype,{preventDefault:function(){this.defaultPrevented=!0;var r=this.nativeEvent;r&&(r.preventDefault?r.preventDefault():typeof r.returnValue!="unknown"&&(r.returnValue=!1),this.isDefaultPrevented=Gl)},stopPropagation:function(){var r=this.nativeEvent;r&&(r.stopPropagation?r.stopPropagation():typeof r.cancelBubble!="unknown"&&(r.cancelBubble=!0),this.isPropagationStopped=Gl)},persist:function(){},isPersistent:Gl}),n}var Nr={eventPhase:0,bubbles:0,cancelable:0,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:0,isTrusted:0},Yl=fn(Nr),yi=p({},Nr,{view:0,detail:0}),H6=fn(yi),Ec,Sc,Ai,Ql=p({},yi,{screenX:0,screenY:0,clientX:0,clientY:0,pageX:0,pageY:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,getModifierState:wc,button:0,buttons:0,relatedTarget:function(e){return e.relatedTarget===void 0?e.fromElement===e.srcElement?e.toElement:e.fromElement:e.relatedTarget},movementX:function(e){return"movementX"in e?e.movementX:(e!==Ai&&(Ai&&e.type==="mousemove"?(Ec=e.screenX-Ai.screenX,Sc=e.screenY-Ai.screenY):Sc=Ec=0,Ai=e),Ec)},movementY:function(e){return"movementY"in e?e.movementY:Sc}}),gh=fn(Ql),B6=p({},Ql,{dataTransfer:0}),$6=fn(B6),V6=p({},yi,{relatedTarget:0}),xc=fn(V6),q6=p({},Nr,{animationName:0,elapsedTime:0,pseudoElement:0}),G6=fn(q6),Y6=p({},Nr,{clipboardData:function(e){return"clipboardData"in e?e.clipboardData:window.clipboardData}}),Q6=fn(Y6),K6=p({},Nr,{data:0}),yh=fn(K6),X6={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},Z6={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"},J6={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};function W6(e){var n=this.nativeEvent;return n.getModifierState?n.getModifierState(e):(e=J6[e])?!!n[e]:!1}function wc(){return W6}var e9=p({},yi,{key:function(e){if(e.key){var n=X6[e.key]||e.key;if(n!=="Unidentified")return n}return e.type==="keypress"?(e=ql(e),e===13?"Enter":String.fromCharCode(e)):e.type==="keydown"||e.type==="keyup"?Z6[e.keyCode]||"Unidentified":""},code:0,location:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,repeat:0,locale:0,getModifierState:wc,charCode:function(e){return e.type==="keypress"?ql(e):0},keyCode:function(e){return e.type==="keydown"||e.type==="keyup"?e.keyCode:0},which:function(e){return e.type==="keypress"?ql(e):e.type==="keydown"||e.type==="keyup"?e.keyCode:0}}),t9=fn(e9),n9=p({},Ql,{pointerId:0,width:0,height:0,pressure:0,tangentialPressure:0,tiltX:0,tiltY:0,twist:0,pointerType:0,isPrimary:0}),Ah=fn(n9),a9=p({},yi,{touches:0,targetTouches:0,changedTouches:0,altKey:0,metaKey:0,ctrlKey:0,shiftKey:0,getModifierState:wc}),r9=fn(a9),o9=p({},Nr,{propertyName:0,elapsedTime:0,pseudoElement:0}),i9=fn(o9),l9=p({},Ql,{deltaX:function(e){return"deltaX"in e?e.deltaX:"wheelDeltaX"in e?-e.wheelDeltaX:0},deltaY:function(e){return"deltaY"in e?e.deltaY:"wheelDeltaY"in e?-e.wheelDeltaY:"wheelDelta"in e?-e.wheelDelta:0},deltaZ:0,deltaMode:0}),s9=fn(l9),u9=p({},Nr,{newState:0,oldState:0}),c9=fn(u9),f9=[9,13,27,32],_c=xa&&"CompositionEvent"in window,Ci=null;xa&&"documentMode"in document&&(Ci=document.documentMode);var d9=xa&&"TextEvent"in window&&!Ci,Ch=xa&&(!_c||Ci&&8<Ci&&11>=Ci),bh=" ",Eh=!1;function Sh(e,n){switch(e){case"keyup":return f9.indexOf(n.keyCode)!==-1;case"keydown":return n.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function xh(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var vo=!1;function h9(e,n){switch(e){case"compositionend":return xh(n);case"keypress":return n.which!==32?null:(Eh=!0,bh);case"textInput":return e=n.data,e===bh&&Eh?null:e;default:return null}}function p9(e,n){if(vo)return e==="compositionend"||!_c&&Sh(e,n)?(e=mh(),Vl=bc=Xa=null,vo=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(n.ctrlKey||n.altKey||n.metaKey)||n.ctrlKey&&n.altKey){if(n.char&&1<n.char.length)return n.char;if(n.which)return String.fromCharCode(n.which)}return null;case"compositionend":return Ch&&n.locale!=="ko"?null:n.data;default:return null}}var m9={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function wh(e){var n=e&&e.nodeName&&e.nodeName.toLowerCase();return n==="input"?!!m9[e.type]:n==="textarea"}function _h(e,n,r,l){po?mo?mo.push(l):mo=[l]:po=l,n=zs(n,"onChange"),0<n.length&&(r=new Yl("onChange","change",null,r,l),e.push({event:r,listeners:n}))}var bi=null,Ei=null;function v9(e){sv(e,0)}function Kl(e){var n=Ke(e);if(Hl(n))return e}function Rh(e,n){if(e==="change")return n}var Th=!1;if(xa){var Rc;if(xa){var Tc="oninput"in document;if(!Tc){var Mh=document.createElement("div");Mh.setAttribute("oninput","return;"),Tc=typeof Mh.oninput=="function"}Rc=Tc}else Rc=!1;Th=Rc&&(!document.documentMode||9<document.documentMode)}function Dh(){bi&&(bi.detachEvent("onpropertychange",Oh),Ei=bi=null)}function Oh(e){if(e.propertyName==="value"&&Kl(Ei)){var n=[];_h(n,Ei,e,yc(e)),ph(v9,n)}}function g9(e,n,r){e==="focusin"?(Dh(),bi=n,Ei=r,bi.attachEvent("onpropertychange",Oh)):e==="focusout"&&Dh()}function y9(e){if(e==="selectionchange"||e==="keyup"||e==="keydown")return Kl(Ei)}function A9(e,n){if(e==="click")return Kl(n)}function C9(e,n){if(e==="input"||e==="change")return Kl(n)}function b9(e,n){return e===n&&(e!==0||1/e===1/n)||e!==e&&n!==n}var An=typeof Object.is=="function"?Object.is:b9;function Si(e,n){if(An(e,n))return!0;if(typeof e!="object"||e===null||typeof n!="object"||n===null)return!1;var r=Object.keys(e),l=Object.keys(n);if(r.length!==l.length)return!1;for(l=0;l<r.length;l++){var f=r[l];if(!yn.call(n,f)||!An(e[f],n[f]))return!1}return!0}function Nh(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function Lh(e,n){var r=Nh(e);e=0;for(var l;r;){if(r.nodeType===3){if(l=e+r.textContent.length,e<=n&&l>=n)return{node:r,offset:n-e};e=l}e:{for(;r;){if(r.nextSibling){r=r.nextSibling;break e}r=r.parentNode}r=void 0}r=Nh(r)}}function jh(e,n){return e&&n?e===n?!0:e&&e.nodeType===3?!1:n&&n.nodeType===3?jh(e,n.parentNode):"contains"in e?e.contains(n):e.compareDocumentPosition?!!(e.compareDocumentPosition(n)&16):!1:!1}function Fh(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var n=Bl(e.document);n instanceof e.HTMLIFrameElement;){try{var r=typeof n.contentWindow.location.href=="string"}catch{r=!1}if(r)e=n.contentWindow;else break;n=Bl(e.document)}return n}function Mc(e){var n=e&&e.nodeName&&e.nodeName.toLowerCase();return n&&(n==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||n==="textarea"||e.contentEditable==="true")}var E9=xa&&"documentMode"in document&&11>=document.documentMode,go=null,Dc=null,xi=null,Oc=!1;function kh(e,n,r){var l=r.window===r?r.document:r.nodeType===9?r:r.ownerDocument;Oc||go==null||go!==Bl(l)||(l=go,"selectionStart"in l&&Mc(l)?l={start:l.selectionStart,end:l.selectionEnd}:(l=(l.ownerDocument&&l.ownerDocument.defaultView||window).getSelection(),l={anchorNode:l.anchorNode,anchorOffset:l.anchorOffset,focusNode:l.focusNode,focusOffset:l.focusOffset}),xi&&Si(xi,l)||(xi=l,l=zs(Dc,"onSelect"),0<l.length&&(n=new Yl("onSelect","select",null,n,r),e.push({event:n,listeners:l}),n.target=go)))}function Lr(e,n){var r={};return r[e.toLowerCase()]=n.toLowerCase(),r["Webkit"+e]="webkit"+n,r["Moz"+e]="moz"+n,r}var yo={animationend:Lr("Animation","AnimationEnd"),animationiteration:Lr("Animation","AnimationIteration"),animationstart:Lr("Animation","AnimationStart"),transitionrun:Lr("Transition","TransitionRun"),transitionstart:Lr("Transition","TransitionStart"),transitioncancel:Lr("Transition","TransitionCancel"),transitionend:Lr("Transition","TransitionEnd")},Nc={},zh={};xa&&(zh=document.createElement("div").style,"AnimationEvent"in window||(delete yo.animationend.animation,delete yo.animationiteration.animation,delete yo.animationstart.animation),"TransitionEvent"in window||delete yo.transitionend.transition);function jr(e){if(Nc[e])return Nc[e];if(!yo[e])return e;var n=yo[e],r;for(r in n)if(n.hasOwnProperty(r)&&r in zh)return Nc[e]=n[r];return e}var Uh=jr("animationend"),Ph=jr("animationiteration"),Ih=jr("animationstart"),S9=jr("transitionrun"),x9=jr("transitionstart"),w9=jr("transitioncancel"),Hh=jr("transitionend"),Bh=new Map,Lc="abort auxClick beforeToggle cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(" ");Lc.push("scrollEnd");function Jn(e,n){Bh.set(e,n),Gt(n,[e])}var Xl=typeof reportError=="function"?reportError:function(e){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var n=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof e=="object"&&e!==null&&typeof e.message=="string"?String(e.message):String(e),error:e});if(!window.dispatchEvent(n))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",e);return}console.error(e)},jn=[],Ao=0,jc=0;function Zl(){for(var e=Ao,n=jc=Ao=0;n<e;){var r=jn[n];jn[n++]=null;var l=jn[n];jn[n++]=null;var f=jn[n];jn[n++]=null;var h=jn[n];if(jn[n++]=null,l!==null&&f!==null){var E=l.pending;E===null?f.next=f:(f.next=E.next,E.next=f),l.pending=f}h!==0&&$h(r,f,h)}}function Jl(e,n,r,l){jn[Ao++]=e,jn[Ao++]=n,jn[Ao++]=r,jn[Ao++]=l,jc|=l,e.lanes|=l,e=e.alternate,e!==null&&(e.lanes|=l)}function Fc(e,n,r,l){return Jl(e,n,r,l),Wl(e)}function Fr(e,n){return Jl(e,null,null,n),Wl(e)}function $h(e,n,r){e.lanes|=r;var l=e.alternate;l!==null&&(l.lanes|=r);for(var f=!1,h=e.return;h!==null;)h.childLanes|=r,l=h.alternate,l!==null&&(l.childLanes|=r),h.tag===22&&(e=h.stateNode,e===null||e._visibility&1||(f=!0)),e=h,h=h.return;return e.tag===3?(h=e.stateNode,f&&n!==null&&(f=31-tn(r),e=h.hiddenUpdates,l=e[f],l===null?e[f]=[n]:l.push(n),n.lane=r|536870912),h):null}function Wl(e){if(50<Gi)throw Gi=0,V0=null,Error(i(185));for(var n=e.return;n!==null;)e=n,n=e.return;return e.tag===3?e.stateNode:null}var Co={};function _9(e,n,r,l){this.tag=e,this.key=r,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.refCleanup=this.ref=null,this.pendingProps=n,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=l,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Cn(e,n,r,l){return new _9(e,n,r,l)}function kc(e){return e=e.prototype,!(!e||!e.isReactComponent)}function wa(e,n){var r=e.alternate;return r===null?(r=Cn(e.tag,n,e.key,e.mode),r.elementType=e.elementType,r.type=e.type,r.stateNode=e.stateNode,r.alternate=e,e.alternate=r):(r.pendingProps=n,r.type=e.type,r.flags=0,r.subtreeFlags=0,r.deletions=null),r.flags=e.flags&65011712,r.childLanes=e.childLanes,r.lanes=e.lanes,r.child=e.child,r.memoizedProps=e.memoizedProps,r.memoizedState=e.memoizedState,r.updateQueue=e.updateQueue,n=e.dependencies,r.dependencies=n===null?null:{lanes:n.lanes,firstContext:n.firstContext},r.sibling=e.sibling,r.index=e.index,r.ref=e.ref,r.refCleanup=e.refCleanup,r}function Vh(e,n){e.flags&=65011714;var r=e.alternate;return r===null?(e.childLanes=0,e.lanes=n,e.child=null,e.subtreeFlags=0,e.memoizedProps=null,e.memoizedState=null,e.updateQueue=null,e.dependencies=null,e.stateNode=null):(e.childLanes=r.childLanes,e.lanes=r.lanes,e.child=r.child,e.subtreeFlags=0,e.deletions=null,e.memoizedProps=r.memoizedProps,e.memoizedState=r.memoizedState,e.updateQueue=r.updateQueue,e.type=r.type,n=r.dependencies,e.dependencies=n===null?null:{lanes:n.lanes,firstContext:n.firstContext}),e}function es(e,n,r,l,f,h){var E=0;if(l=e,typeof e=="function")kc(e)&&(E=1);else if(typeof e=="string")E=O4(e,r,ie.current)?26:e==="html"||e==="head"||e==="body"?27:5;else e:switch(e){case I:return e=Cn(31,r,n,f),e.elementType=I,e.lanes=h,e;case x:return kr(r.children,f,h,n);case w:E=8,f|=24;break;case D:return e=Cn(12,r,n,f|2),e.elementType=D,e.lanes=h,e;case N:return e=Cn(13,r,n,f),e.elementType=N,e.lanes=h,e;case j:return e=Cn(19,r,n,f),e.elementType=j,e.lanes=h,e;default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case R:E=10;break e;case T:E=9;break e;case _:E=11;break e;case F:E=14;break e;case O:E=16,l=null;break e}E=29,r=Error(i(130,e===null?"null":typeof e,"")),l=null}return n=Cn(E,r,n,f),n.elementType=e,n.type=l,n.lanes=h,n}function kr(e,n,r,l){return e=Cn(7,e,l,n),e.lanes=r,e}function zc(e,n,r){return e=Cn(6,e,null,n),e.lanes=r,e}function qh(e){var n=Cn(18,null,null,0);return n.stateNode=e,n}function Uc(e,n,r){return n=Cn(4,e.children!==null?e.children:[],e.key,n),n.lanes=r,n.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},n}var Gh=new WeakMap;function Fn(e,n){if(typeof e=="object"&&e!==null){var r=Gh.get(e);return r!==void 0?r:(n={value:e,source:n,stack:en(n)},Gh.set(e,n),n)}return{value:e,source:n,stack:en(n)}}var bo=[],Eo=0,ts=null,wi=0,kn=[],zn=0,Za=null,fa=1,da="";function _a(e,n){bo[Eo++]=wi,bo[Eo++]=ts,ts=e,wi=n}function Yh(e,n,r){kn[zn++]=fa,kn[zn++]=da,kn[zn++]=Za,Za=e;var l=fa;e=da;var f=32-tn(l)-1;l&=~(1<<f),r+=1;var h=32-tn(n)+f;if(30<h){var E=f-f%5;h=(l&(1<<E)-1).toString(32),l>>=E,f-=E,fa=1<<32-tn(n)+f|r<<f|l,da=h+e}else fa=1<<h|r<<f|l,da=e}function Pc(e){e.return!==null&&(_a(e,1),Yh(e,1,0))}function Ic(e){for(;e===ts;)ts=bo[--Eo],bo[Eo]=null,wi=bo[--Eo],bo[Eo]=null;for(;e===Za;)Za=kn[--zn],kn[zn]=null,da=kn[--zn],kn[zn]=null,fa=kn[--zn],kn[zn]=null}function Qh(e,n){kn[zn++]=fa,kn[zn++]=da,kn[zn++]=Za,fa=n.id,da=n.overflow,Za=e}var Kt=null,Et=null,Qe=!1,Ja=null,Un=!1,Hc=Error(i(519));function Wa(e){var n=Error(i(418,1<arguments.length&&arguments[1]!==void 0&&arguments[1]?"text":"HTML",""));throw _i(Fn(n,e)),Hc}function Kh(e){var n=e.stateNode,r=e.type,l=e.memoizedProps;switch(n[Ce]=e,n[be]=l,r){case"dialog":qe("cancel",n),qe("close",n);break;case"iframe":case"object":case"embed":qe("load",n);break;case"video":case"audio":for(r=0;r<Qi.length;r++)qe(Qi[r],n);break;case"source":qe("error",n);break;case"img":case"image":case"link":qe("error",n),qe("load",n);break;case"details":qe("toggle",n);break;case"input":qe("invalid",n),sh(n,l.value,l.defaultValue,l.checked,l.defaultChecked,l.type,l.name,!0);break;case"select":qe("invalid",n);break;case"textarea":qe("invalid",n),ch(n,l.value,l.defaultValue,l.children)}r=l.children,typeof r!="string"&&typeof r!="number"&&typeof r!="bigint"||n.textContent===""+r||l.suppressHydrationWarning===!0||dv(n.textContent,r)?(l.popover!=null&&(qe("beforetoggle",n),qe("toggle",n)),l.onScroll!=null&&qe("scroll",n),l.onScrollEnd!=null&&qe("scrollend",n),l.onClick!=null&&(n.onclick=Sa),n=!0):n=!1,n||Wa(e,!0)}function Xh(e){for(Kt=e.return;Kt;)switch(Kt.tag){case 5:case 31:case 13:Un=!1;return;case 27:case 3:Un=!0;return;default:Kt=Kt.return}}function So(e){if(e!==Kt)return!1;if(!Qe)return Xh(e),Qe=!0,!1;var n=e.tag,r;if((r=n!==3&&n!==27)&&((r=n===5)&&(r=e.type,r=!(r!=="form"&&r!=="button")||o2(e.type,e.memoizedProps)),r=!r),r&&Et&&Wa(e),Xh(e),n===13){if(e=e.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(i(317));Et=bv(e)}else if(n===31){if(e=e.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(i(317));Et=bv(e)}else n===27?(n=Et,hr(e.type)?(e=c2,c2=null,Et=e):Et=n):Et=Kt?In(e.stateNode.nextSibling):null;return!0}function zr(){Et=Kt=null,Qe=!1}function Bc(){var e=Ja;return e!==null&&(mn===null?mn=e:mn.push.apply(mn,e),Ja=null),e}function _i(e){Ja===null?Ja=[e]:Ja.push(e)}var $c=L(null),Ur=null,Ra=null;function er(e,n,r){ne($c,n._currentValue),n._currentValue=r}function Ta(e){e._currentValue=$c.current,$($c)}function Vc(e,n,r){for(;e!==null;){var l=e.alternate;if((e.childLanes&n)!==n?(e.childLanes|=n,l!==null&&(l.childLanes|=n)):l!==null&&(l.childLanes&n)!==n&&(l.childLanes|=n),e===r)break;e=e.return}}function qc(e,n,r,l){var f=e.child;for(f!==null&&(f.return=e);f!==null;){var h=f.dependencies;if(h!==null){var E=f.child;h=h.firstContext;e:for(;h!==null;){var M=h;h=f;for(var k=0;k<n.length;k++)if(M.context===n[k]){h.lanes|=r,M=h.alternate,M!==null&&(M.lanes|=r),Vc(h.return,r,e),l||(E=null);break e}h=M.next}}else if(f.tag===18){if(E=f.return,E===null)throw Error(i(341));E.lanes|=r,h=E.alternate,h!==null&&(h.lanes|=r),Vc(E,r,e),E=null}else E=f.child;if(E!==null)E.return=f;else for(E=f;E!==null;){if(E===e){E=null;break}if(f=E.sibling,f!==null){f.return=E.return,E=f;break}E=E.return}f=E}}function xo(e,n,r,l){e=null;for(var f=n,h=!1;f!==null;){if(!h){if((f.flags&524288)!==0)h=!0;else if((f.flags&262144)!==0)break}if(f.tag===10){var E=f.alternate;if(E===null)throw Error(i(387));if(E=E.memoizedProps,E!==null){var M=f.type;An(f.pendingProps.value,E.value)||(e!==null?e.push(M):e=[M])}}else if(f===ue.current){if(E=f.alternate,E===null)throw Error(i(387));E.memoizedState.memoizedState!==f.memoizedState.memoizedState&&(e!==null?e.push(Wi):e=[Wi])}f=f.return}e!==null&&qc(n,e,r,l),n.flags|=262144}function ns(e){for(e=e.firstContext;e!==null;){if(!An(e.context._currentValue,e.memoizedValue))return!0;e=e.next}return!1}function Pr(e){Ur=e,Ra=null,e=e.dependencies,e!==null&&(e.firstContext=null)}function Xt(e){return Zh(Ur,e)}function as(e,n){return Ur===null&&Pr(e),Zh(e,n)}function Zh(e,n){var r=n._currentValue;if(n={context:n,memoizedValue:r,next:null},Ra===null){if(e===null)throw Error(i(308));Ra=n,e.dependencies={lanes:0,firstContext:n},e.flags|=524288}else Ra=Ra.next=n;return r}var R9=typeof AbortController<"u"?AbortController:function(){var e=[],n=this.signal={aborted:!1,addEventListener:function(r,l){e.push(l)}};this.abort=function(){n.aborted=!0,e.forEach(function(r){return r()})}},T9=t.unstable_scheduleCallback,M9=t.unstable_NormalPriority,It={$$typeof:R,Consumer:null,Provider:null,_currentValue:null,_currentValue2:null,_threadCount:0};function Gc(){return{controller:new R9,data:new Map,refCount:0}}function Ri(e){e.refCount--,e.refCount===0&&T9(M9,function(){e.controller.abort()})}var Ti=null,Yc=0,wo=0,_o=null;function D9(e,n){if(Ti===null){var r=Ti=[];Yc=0,wo=X0(),_o={status:"pending",value:void 0,then:function(l){r.push(l)}}}return Yc++,n.then(Jh,Jh),n}function Jh(){if(--Yc===0&&Ti!==null){_o!==null&&(_o.status="fulfilled");var e=Ti;Ti=null,wo=0,_o=null;for(var n=0;n<e.length;n++)(0,e[n])()}}function O9(e,n){var r=[],l={status:"pending",value:null,reason:null,then:function(f){r.push(f)}};return e.then(function(){l.status="fulfilled",l.value=n;for(var f=0;f<r.length;f++)(0,r[f])(n)},function(f){for(l.status="rejected",l.reason=f,f=0;f<r.length;f++)(0,r[f])(void 0)}),l}var Wh=U.S;U.S=function(e,n){km=kt(),typeof n=="object"&&n!==null&&typeof n.then=="function"&&D9(e,n),Wh!==null&&Wh(e,n)};var Ir=L(null);function Qc(){var e=Ir.current;return e!==null?e:ht.pooledCache}function rs(e,n){n===null?ne(Ir,Ir.current):ne(Ir,n.pool)}function ep(){var e=Qc();return e===null?null:{parent:It._currentValue,pool:e}}var Ro=Error(i(460)),Kc=Error(i(474)),os=Error(i(542)),is={then:function(){}};function tp(e){return e=e.status,e==="fulfilled"||e==="rejected"}function np(e,n,r){switch(r=e[r],r===void 0?e.push(n):r!==n&&(n.then(Sa,Sa),n=r),n.status){case"fulfilled":return n.value;case"rejected":throw e=n.reason,rp(e),e;default:if(typeof n.status=="string")n.then(Sa,Sa);else{if(e=ht,e!==null&&100<e.shellSuspendCounter)throw Error(i(482));e=n,e.status="pending",e.then(function(l){if(n.status==="pending"){var f=n;f.status="fulfilled",f.value=l}},function(l){if(n.status==="pending"){var f=n;f.status="rejected",f.reason=l}})}switch(n.status){case"fulfilled":return n.value;case"rejected":throw e=n.reason,rp(e),e}throw Br=n,Ro}}function Hr(e){try{var n=e._init;return n(e._payload)}catch(r){throw r!==null&&typeof r=="object"&&typeof r.then=="function"?(Br=r,Ro):r}}var Br=null;function ap(){if(Br===null)throw Error(i(459));var e=Br;return Br=null,e}function rp(e){if(e===Ro||e===os)throw Error(i(483))}var To=null,Mi=0;function ls(e){var n=Mi;return Mi+=1,To===null&&(To=[]),np(To,e,n)}function Di(e,n){n=n.props.ref,e.ref=n!==void 0?n:null}function ss(e,n){throw n.$$typeof===C?Error(i(525)):(e=Object.prototype.toString.call(n),Error(i(31,e==="[object Object]"?"object with keys {"+Object.keys(n).join(", ")+"}":e)))}function op(e){function n(V,P){if(e){var Y=V.deletions;Y===null?(V.deletions=[P],V.flags|=16):Y.push(P)}}function r(V,P){if(!e)return null;for(;P!==null;)n(V,P),P=P.sibling;return null}function l(V){for(var P=new Map;V!==null;)V.key!==null?P.set(V.key,V):P.set(V.index,V),V=V.sibling;return P}function f(V,P){return V=wa(V,P),V.index=0,V.sibling=null,V}function h(V,P,Y){return V.index=Y,e?(Y=V.alternate,Y!==null?(Y=Y.index,Y<P?(V.flags|=67108866,P):Y):(V.flags|=67108866,P)):(V.flags|=1048576,P)}function E(V){return e&&V.alternate===null&&(V.flags|=67108866),V}function M(V,P,Y,oe){return P===null||P.tag!==6?(P=zc(Y,V.mode,oe),P.return=V,P):(P=f(P,Y),P.return=V,P)}function k(V,P,Y,oe){var Oe=Y.type;return Oe===x?ae(V,P,Y.props.children,oe,Y.key):P!==null&&(P.elementType===Oe||typeof Oe=="object"&&Oe!==null&&Oe.$$typeof===O&&Hr(Oe)===P.type)?(P=f(P,Y.props),Di(P,Y),P.return=V,P):(P=es(Y.type,Y.key,Y.props,null,V.mode,oe),Di(P,Y),P.return=V,P)}function Q(V,P,Y,oe){return P===null||P.tag!==4||P.stateNode.containerInfo!==Y.containerInfo||P.stateNode.implementation!==Y.implementation?(P=Uc(Y,V.mode,oe),P.return=V,P):(P=f(P,Y.children||[]),P.return=V,P)}function ae(V,P,Y,oe,Oe){return P===null||P.tag!==7?(P=kr(Y,V.mode,oe,Oe),P.return=V,P):(P=f(P,Y),P.return=V,P)}function le(V,P,Y){if(typeof P=="string"&&P!==""||typeof P=="number"||typeof P=="bigint")return P=zc(""+P,V.mode,Y),P.return=V,P;if(typeof P=="object"&&P!==null){switch(P.$$typeof){case b:return Y=es(P.type,P.key,P.props,null,V.mode,Y),Di(Y,P),Y.return=V,Y;case S:return P=Uc(P,V.mode,Y),P.return=V,P;case O:return P=Hr(P),le(V,P,Y)}if(fe(P)||ce(P))return P=kr(P,V.mode,Y,null),P.return=V,P;if(typeof P.then=="function")return le(V,ls(P),Y);if(P.$$typeof===R)return le(V,as(V,P),Y);ss(V,P)}return null}function Z(V,P,Y,oe){var Oe=P!==null?P.key:null;if(typeof Y=="string"&&Y!==""||typeof Y=="number"||typeof Y=="bigint")return Oe!==null?null:M(V,P,""+Y,oe);if(typeof Y=="object"&&Y!==null){switch(Y.$$typeof){case b:return Y.key===Oe?k(V,P,Y,oe):null;case S:return Y.key===Oe?Q(V,P,Y,oe):null;case O:return Y=Hr(Y),Z(V,P,Y,oe)}if(fe(Y)||ce(Y))return Oe!==null?null:ae(V,P,Y,oe,null);if(typeof Y.then=="function")return Z(V,P,ls(Y),oe);if(Y.$$typeof===R)return Z(V,P,as(V,Y),oe);ss(V,Y)}return null}function ee(V,P,Y,oe,Oe){if(typeof oe=="string"&&oe!==""||typeof oe=="number"||typeof oe=="bigint")return V=V.get(Y)||null,M(P,V,""+oe,Oe);if(typeof oe=="object"&&oe!==null){switch(oe.$$typeof){case b:return V=V.get(oe.key===null?Y:oe.key)||null,k(P,V,oe,Oe);case S:return V=V.get(oe.key===null?Y:oe.key)||null,Q(P,V,oe,Oe);case O:return oe=Hr(oe),ee(V,P,Y,oe,Oe)}if(fe(oe)||ce(oe))return V=V.get(Y)||null,ae(P,V,oe,Oe,null);if(typeof oe.then=="function")return ee(V,P,Y,ls(oe),Oe);if(oe.$$typeof===R)return ee(V,P,Y,as(P,oe),Oe);ss(P,oe)}return null}function xe(V,P,Y,oe){for(var Oe=null,et=null,Me=P,Pe=P=0,Ye=null;Me!==null&&Pe<Y.length;Pe++){Me.index>Pe?(Ye=Me,Me=null):Ye=Me.sibling;var tt=Z(V,Me,Y[Pe],oe);if(tt===null){Me===null&&(Me=Ye);break}e&&Me&&tt.alternate===null&&n(V,Me),P=h(tt,P,Pe),et===null?Oe=tt:et.sibling=tt,et=tt,Me=Ye}if(Pe===Y.length)return r(V,Me),Qe&&_a(V,Pe),Oe;if(Me===null){for(;Pe<Y.length;Pe++)Me=le(V,Y[Pe],oe),Me!==null&&(P=h(Me,P,Pe),et===null?Oe=Me:et.sibling=Me,et=Me);return Qe&&_a(V,Pe),Oe}for(Me=l(Me);Pe<Y.length;Pe++)Ye=ee(Me,V,Pe,Y[Pe],oe),Ye!==null&&(e&&Ye.alternate!==null&&Me.delete(Ye.key===null?Pe:Ye.key),P=h(Ye,P,Pe),et===null?Oe=Ye:et.sibling=Ye,et=Ye);return e&&Me.forEach(function(yr){return n(V,yr)}),Qe&&_a(V,Pe),Oe}function Le(V,P,Y,oe){if(Y==null)throw Error(i(151));for(var Oe=null,et=null,Me=P,Pe=P=0,Ye=null,tt=Y.next();Me!==null&&!tt.done;Pe++,tt=Y.next()){Me.index>Pe?(Ye=Me,Me=null):Ye=Me.sibling;var yr=Z(V,Me,tt.value,oe);if(yr===null){Me===null&&(Me=Ye);break}e&&Me&&yr.alternate===null&&n(V,Me),P=h(yr,P,Pe),et===null?Oe=yr:et.sibling=yr,et=yr,Me=Ye}if(tt.done)return r(V,Me),Qe&&_a(V,Pe),Oe;if(Me===null){for(;!tt.done;Pe++,tt=Y.next())tt=le(V,tt.value,oe),tt!==null&&(P=h(tt,P,Pe),et===null?Oe=tt:et.sibling=tt,et=tt);return Qe&&_a(V,Pe),Oe}for(Me=l(Me);!tt.done;Pe++,tt=Y.next())tt=ee(Me,V,Pe,tt.value,oe),tt!==null&&(e&&tt.alternate!==null&&Me.delete(tt.key===null?Pe:tt.key),P=h(tt,P,Pe),et===null?Oe=tt:et.sibling=tt,et=tt);return e&&Me.forEach(function(B4){return n(V,B4)}),Qe&&_a(V,Pe),Oe}function ct(V,P,Y,oe){if(typeof Y=="object"&&Y!==null&&Y.type===x&&Y.key===null&&(Y=Y.props.children),typeof Y=="object"&&Y!==null){switch(Y.$$typeof){case b:e:{for(var Oe=Y.key;P!==null;){if(P.key===Oe){if(Oe=Y.type,Oe===x){if(P.tag===7){r(V,P.sibling),oe=f(P,Y.props.children),oe.return=V,V=oe;break e}}else if(P.elementType===Oe||typeof Oe=="object"&&Oe!==null&&Oe.$$typeof===O&&Hr(Oe)===P.type){r(V,P.sibling),oe=f(P,Y.props),Di(oe,Y),oe.return=V,V=oe;break e}r(V,P);break}else n(V,P);P=P.sibling}Y.type===x?(oe=kr(Y.props.children,V.mode,oe,Y.key),oe.return=V,V=oe):(oe=es(Y.type,Y.key,Y.props,null,V.mode,oe),Di(oe,Y),oe.return=V,V=oe)}return E(V);case S:e:{for(Oe=Y.key;P!==null;){if(P.key===Oe)if(P.tag===4&&P.stateNode.containerInfo===Y.containerInfo&&P.stateNode.implementation===Y.implementation){r(V,P.sibling),oe=f(P,Y.children||[]),oe.return=V,V=oe;break e}else{r(V,P);break}else n(V,P);P=P.sibling}oe=Uc(Y,V.mode,oe),oe.return=V,V=oe}return E(V);case O:return Y=Hr(Y),ct(V,P,Y,oe)}if(fe(Y))return xe(V,P,Y,oe);if(ce(Y)){if(Oe=ce(Y),typeof Oe!="function")throw Error(i(150));return Y=Oe.call(Y),Le(V,P,Y,oe)}if(typeof Y.then=="function")return ct(V,P,ls(Y),oe);if(Y.$$typeof===R)return ct(V,P,as(V,Y),oe);ss(V,Y)}return typeof Y=="string"&&Y!==""||typeof Y=="number"||typeof Y=="bigint"?(Y=""+Y,P!==null&&P.tag===6?(r(V,P.sibling),oe=f(P,Y),oe.return=V,V=oe):(r(V,P),oe=zc(Y,V.mode,oe),oe.return=V,V=oe),E(V)):r(V,P)}return function(V,P,Y,oe){try{Mi=0;var Oe=ct(V,P,Y,oe);return To=null,Oe}catch(Me){if(Me===Ro||Me===os)throw Me;var et=Cn(29,Me,null,V.mode);return et.lanes=oe,et.return=V,et}}}var $r=op(!0),ip=op(!1),tr=!1;function Xc(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Zc(e,n){e=e.updateQueue,n.updateQueue===e&&(n.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function nr(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function ar(e,n,r){var l=e.updateQueue;if(l===null)return null;if(l=l.shared,(nt&2)!==0){var f=l.pending;return f===null?n.next=n:(n.next=f.next,f.next=n),l.pending=n,n=Wl(e),$h(e,null,r),n}return Jl(e,l,n,r),Wl(e)}function Oi(e,n,r){if(n=n.updateQueue,n!==null&&(n=n.shared,(r&4194048)!==0)){var l=n.lanes;l&=e.pendingLanes,r|=l,n.lanes=r,Il(e,r)}}function Jc(e,n){var r=e.updateQueue,l=e.alternate;if(l!==null&&(l=l.updateQueue,r===l)){var f=null,h=null;if(r=r.firstBaseUpdate,r!==null){do{var E={lane:r.lane,tag:r.tag,payload:r.payload,callback:null,next:null};h===null?f=h=E:h=h.next=E,r=r.next}while(r!==null);h===null?f=h=n:h=h.next=n}else f=h=n;r={baseState:l.baseState,firstBaseUpdate:f,lastBaseUpdate:h,shared:l.shared,callbacks:l.callbacks},e.updateQueue=r;return}e=r.lastBaseUpdate,e===null?r.firstBaseUpdate=n:e.next=n,r.lastBaseUpdate=n}var Wc=!1;function Ni(){if(Wc){var e=_o;if(e!==null)throw e}}function Li(e,n,r,l){Wc=!1;var f=e.updateQueue;tr=!1;var h=f.firstBaseUpdate,E=f.lastBaseUpdate,M=f.shared.pending;if(M!==null){f.shared.pending=null;var k=M,Q=k.next;k.next=null,E===null?h=Q:E.next=Q,E=k;var ae=e.alternate;ae!==null&&(ae=ae.updateQueue,M=ae.lastBaseUpdate,M!==E&&(M===null?ae.firstBaseUpdate=Q:M.next=Q,ae.lastBaseUpdate=k))}if(h!==null){var le=f.baseState;E=0,ae=Q=k=null,M=h;do{var Z=M.lane&-536870913,ee=Z!==M.lane;if(ee?(Ge&Z)===Z:(l&Z)===Z){Z!==0&&Z===wo&&(Wc=!0),ae!==null&&(ae=ae.next={lane:0,tag:M.tag,payload:M.payload,callback:null,next:null});e:{var xe=e,Le=M;Z=n;var ct=r;switch(Le.tag){case 1:if(xe=Le.payload,typeof xe=="function"){le=xe.call(ct,le,Z);break e}le=xe;break e;case 3:xe.flags=xe.flags&-65537|128;case 0:if(xe=Le.payload,Z=typeof xe=="function"?xe.call(ct,le,Z):xe,Z==null)break e;le=p({},le,Z);break e;case 2:tr=!0}}Z=M.callback,Z!==null&&(e.flags|=64,ee&&(e.flags|=8192),ee=f.callbacks,ee===null?f.callbacks=[Z]:ee.push(Z))}else ee={lane:Z,tag:M.tag,payload:M.payload,callback:M.callback,next:null},ae===null?(Q=ae=ee,k=le):ae=ae.next=ee,E|=Z;if(M=M.next,M===null){if(M=f.shared.pending,M===null)break;ee=M,M=ee.next,ee.next=null,f.lastBaseUpdate=ee,f.shared.pending=null}}while(!0);ae===null&&(k=le),f.baseState=k,f.firstBaseUpdate=Q,f.lastBaseUpdate=ae,h===null&&(f.shared.lanes=0),sr|=E,e.lanes=E,e.memoizedState=le}}function lp(e,n){if(typeof e!="function")throw Error(i(191,e));e.call(n)}function sp(e,n){var r=e.callbacks;if(r!==null)for(e.callbacks=null,e=0;e<r.length;e++)lp(r[e],n)}var Mo=L(null),us=L(0);function up(e,n){e=za,ne(us,e),ne(Mo,n),za=e|n.baseLanes}function e0(){ne(us,za),ne(Mo,Mo.current)}function t0(){za=us.current,$(Mo),$(us)}var bn=L(null),Pn=null;function rr(e){var n=e.alternate;ne(Lt,Lt.current&1),ne(bn,e),Pn===null&&(n===null||Mo.current!==null||n.memoizedState!==null)&&(Pn=e)}function n0(e){ne(Lt,Lt.current),ne(bn,e),Pn===null&&(Pn=e)}function cp(e){e.tag===22?(ne(Lt,Lt.current),ne(bn,e),Pn===null&&(Pn=e)):or()}function or(){ne(Lt,Lt.current),ne(bn,bn.current)}function En(e){$(bn),Pn===e&&(Pn=null),$(Lt)}var Lt=L(0);function cs(e){for(var n=e;n!==null;){if(n.tag===13){var r=n.memoizedState;if(r!==null&&(r=r.dehydrated,r===null||s2(r)||u2(r)))return n}else if(n.tag===19&&(n.memoizedProps.revealOrder==="forwards"||n.memoizedProps.revealOrder==="backwards"||n.memoizedProps.revealOrder==="unstable_legacy-backwards"||n.memoizedProps.revealOrder==="together")){if((n.flags&128)!==0)return n}else if(n.child!==null){n.child.return=n,n=n.child;continue}if(n===e)break;for(;n.sibling===null;){if(n.return===null||n.return===e)return null;n=n.return}n.sibling.return=n.return,n=n.sibling}return null}var Ma=0,ze=null,st=null,Ht=null,fs=!1,Do=!1,Vr=!1,ds=0,ji=0,Oo=null,N9=0;function Tt(){throw Error(i(321))}function a0(e,n){if(n===null)return!1;for(var r=0;r<n.length&&r<e.length;r++)if(!An(e[r],n[r]))return!1;return!0}function r0(e,n,r,l,f,h){return Ma=h,ze=n,n.memoizedState=null,n.updateQueue=null,n.lanes=0,U.H=e===null||e.memoizedState===null?Yp:A0,Vr=!1,h=r(l,f),Vr=!1,Do&&(h=dp(n,r,l,f)),fp(e),h}function fp(e){U.H=zi;var n=st!==null&&st.next!==null;if(Ma=0,Ht=st=ze=null,fs=!1,ji=0,Oo=null,n)throw Error(i(300));e===null||Bt||(e=e.dependencies,e!==null&&ns(e)&&(Bt=!0))}function dp(e,n,r,l){ze=e;var f=0;do{if(Do&&(Oo=null),ji=0,Do=!1,25<=f)throw Error(i(301));if(f+=1,Ht=st=null,e.updateQueue!=null){var h=e.updateQueue;h.lastEffect=null,h.events=null,h.stores=null,h.memoCache!=null&&(h.memoCache.index=0)}U.H=Qp,h=n(r,l)}while(Do);return h}function L9(){var e=U.H,n=e.useState()[0];return n=typeof n.then=="function"?Fi(n):n,e=e.useState()[0],(st!==null?st.memoizedState:null)!==e&&(ze.flags|=1024),n}function o0(){var e=ds!==0;return ds=0,e}function i0(e,n,r){n.updateQueue=e.updateQueue,n.flags&=-2053,e.lanes&=~r}function l0(e){if(fs){for(e=e.memoizedState;e!==null;){var n=e.queue;n!==null&&(n.pending=null),e=e.next}fs=!1}Ma=0,Ht=st=ze=null,Do=!1,ji=ds=0,Oo=null}function sn(){var e={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return Ht===null?ze.memoizedState=Ht=e:Ht=Ht.next=e,Ht}function jt(){if(st===null){var e=ze.alternate;e=e!==null?e.memoizedState:null}else e=st.next;var n=Ht===null?ze.memoizedState:Ht.next;if(n!==null)Ht=n,st=e;else{if(e===null)throw ze.alternate===null?Error(i(467)):Error(i(310));st=e,e={memoizedState:st.memoizedState,baseState:st.baseState,baseQueue:st.baseQueue,queue:st.queue,next:null},Ht===null?ze.memoizedState=Ht=e:Ht=Ht.next=e}return Ht}function hs(){return{lastEffect:null,events:null,stores:null,memoCache:null}}function Fi(e){var n=ji;return ji+=1,Oo===null&&(Oo=[]),e=np(Oo,e,n),n=ze,(Ht===null?n.memoizedState:Ht.next)===null&&(n=n.alternate,U.H=n===null||n.memoizedState===null?Yp:A0),e}function ps(e){if(e!==null&&typeof e=="object"){if(typeof e.then=="function")return Fi(e);if(e.$$typeof===R)return Xt(e)}throw Error(i(438,String(e)))}function s0(e){var n=null,r=ze.updateQueue;if(r!==null&&(n=r.memoCache),n==null){var l=ze.alternate;l!==null&&(l=l.updateQueue,l!==null&&(l=l.memoCache,l!=null&&(n={data:l.data.map(function(f){return f.slice()}),index:0})))}if(n==null&&(n={data:[],index:0}),r===null&&(r=hs(),ze.updateQueue=r),r.memoCache=n,r=n.data[n.index],r===void 0)for(r=n.data[n.index]=Array(e),l=0;l<e;l++)r[l]=re;return n.index++,r}function Da(e,n){return typeof n=="function"?n(e):n}function ms(e){var n=jt();return u0(n,st,e)}function u0(e,n,r){var l=e.queue;if(l===null)throw Error(i(311));l.lastRenderedReducer=r;var f=e.baseQueue,h=l.pending;if(h!==null){if(f!==null){var E=f.next;f.next=h.next,h.next=E}n.baseQueue=f=h,l.pending=null}if(h=e.baseState,f===null)e.memoizedState=h;else{n=f.next;var M=E=null,k=null,Q=n,ae=!1;do{var le=Q.lane&-536870913;if(le!==Q.lane?(Ge&le)===le:(Ma&le)===le){var Z=Q.revertLane;if(Z===0)k!==null&&(k=k.next={lane:0,revertLane:0,gesture:null,action:Q.action,hasEagerState:Q.hasEagerState,eagerState:Q.eagerState,next:null}),le===wo&&(ae=!0);else if((Ma&Z)===Z){Q=Q.next,Z===wo&&(ae=!0);continue}else le={lane:0,revertLane:Q.revertLane,gesture:null,action:Q.action,hasEagerState:Q.hasEagerState,eagerState:Q.eagerState,next:null},k===null?(M=k=le,E=h):k=k.next=le,ze.lanes|=Z,sr|=Z;le=Q.action,Vr&&r(h,le),h=Q.hasEagerState?Q.eagerState:r(h,le)}else Z={lane:le,revertLane:Q.revertLane,gesture:Q.gesture,action:Q.action,hasEagerState:Q.hasEagerState,eagerState:Q.eagerState,next:null},k===null?(M=k=Z,E=h):k=k.next=Z,ze.lanes|=le,sr|=le;Q=Q.next}while(Q!==null&&Q!==n);if(k===null?E=h:k.next=M,!An(h,e.memoizedState)&&(Bt=!0,ae&&(r=_o,r!==null)))throw r;e.memoizedState=h,e.baseState=E,e.baseQueue=k,l.lastRenderedState=h}return f===null&&(l.lanes=0),[e.memoizedState,l.dispatch]}function c0(e){var n=jt(),r=n.queue;if(r===null)throw Error(i(311));r.lastRenderedReducer=e;var l=r.dispatch,f=r.pending,h=n.memoizedState;if(f!==null){r.pending=null;var E=f=f.next;do h=e(h,E.action),E=E.next;while(E!==f);An(h,n.memoizedState)||(Bt=!0),n.memoizedState=h,n.baseQueue===null&&(n.baseState=h),r.lastRenderedState=h}return[h,l]}function hp(e,n,r){var l=ze,f=jt(),h=Qe;if(h){if(r===void 0)throw Error(i(407));r=r()}else r=n();var E=!An((st||f).memoizedState,r);if(E&&(f.memoizedState=r,Bt=!0),f=f.queue,h0(vp.bind(null,l,f,e),[e]),f.getSnapshot!==n||E||Ht!==null&&Ht.memoizedState.tag&1){if(l.flags|=2048,No(9,{destroy:void 0},mp.bind(null,l,f,r,n),null),ht===null)throw Error(i(349));h||(Ma&127)!==0||pp(l,n,r)}return r}function pp(e,n,r){e.flags|=16384,e={getSnapshot:n,value:r},n=ze.updateQueue,n===null?(n=hs(),ze.updateQueue=n,n.stores=[e]):(r=n.stores,r===null?n.stores=[e]:r.push(e))}function mp(e,n,r,l){n.value=r,n.getSnapshot=l,gp(n)&&yp(e)}function vp(e,n,r){return r(function(){gp(n)&&yp(e)})}function gp(e){var n=e.getSnapshot;e=e.value;try{var r=n();return!An(e,r)}catch{return!0}}function yp(e){var n=Fr(e,2);n!==null&&vn(n,e,2)}function f0(e){var n=sn();if(typeof e=="function"){var r=e;if(e=r(),Vr){qt(!0);try{r()}finally{qt(!1)}}}return n.memoizedState=n.baseState=e,n.queue={pending:null,lanes:0,dispatch:null,lastRenderedReducer:Da,lastRenderedState:e},n}function Ap(e,n,r,l){return e.baseState=r,u0(e,st,typeof l=="function"?l:Da)}function j9(e,n,r,l,f){if(ys(e))throw Error(i(485));if(e=n.action,e!==null){var h={payload:f,action:e,next:null,isTransition:!0,status:"pending",value:null,reason:null,listeners:[],then:function(E){h.listeners.push(E)}};U.T!==null?r(!0):h.isTransition=!1,l(h),r=n.pending,r===null?(h.next=n.pending=h,Cp(n,h)):(h.next=r.next,n.pending=r.next=h)}}function Cp(e,n){var r=n.action,l=n.payload,f=e.state;if(n.isTransition){var h=U.T,E={};U.T=E;try{var M=r(f,l),k=U.S;k!==null&&k(E,M),bp(e,n,M)}catch(Q){d0(e,n,Q)}finally{h!==null&&E.types!==null&&(h.types=E.types),U.T=h}}else try{h=r(f,l),bp(e,n,h)}catch(Q){d0(e,n,Q)}}function bp(e,n,r){r!==null&&typeof r=="object"&&typeof r.then=="function"?r.then(function(l){Ep(e,n,l)},function(l){return d0(e,n,l)}):Ep(e,n,r)}function Ep(e,n,r){n.status="fulfilled",n.value=r,Sp(n),e.state=r,n=e.pending,n!==null&&(r=n.next,r===n?e.pending=null:(r=r.next,n.next=r,Cp(e,r)))}function d0(e,n,r){var l=e.pending;if(e.pending=null,l!==null){l=l.next;do n.status="rejected",n.reason=r,Sp(n),n=n.next;while(n!==l)}e.action=null}function Sp(e){e=e.listeners;for(var n=0;n<e.length;n++)(0,e[n])()}function xp(e,n){return n}function wp(e,n){if(Qe){var r=ht.formState;if(r!==null){e:{var l=ze;if(Qe){if(Et){t:{for(var f=Et,h=Un;f.nodeType!==8;){if(!h){f=null;break t}if(f=In(f.nextSibling),f===null){f=null;break t}}h=f.data,f=h==="F!"||h==="F"?f:null}if(f){Et=In(f.nextSibling),l=f.data==="F!";break e}}Wa(l)}l=!1}l&&(n=r[0])}}return r=sn(),r.memoizedState=r.baseState=n,l={pending:null,lanes:0,dispatch:null,lastRenderedReducer:xp,lastRenderedState:n},r.queue=l,r=Vp.bind(null,ze,l),l.dispatch=r,l=f0(!1),h=y0.bind(null,ze,!1,l.queue),l=sn(),f={state:n,dispatch:null,action:e,pending:null},l.queue=f,r=j9.bind(null,ze,f,h,r),f.dispatch=r,l.memoizedState=e,[n,r,!1]}function _p(e){var n=jt();return Rp(n,st,e)}function Rp(e,n,r){if(n=u0(e,n,xp)[0],e=ms(Da)[0],typeof n=="object"&&n!==null&&typeof n.then=="function")try{var l=Fi(n)}catch(E){throw E===Ro?os:E}else l=n;n=jt();var f=n.queue,h=f.dispatch;return r!==n.memoizedState&&(ze.flags|=2048,No(9,{destroy:void 0},F9.bind(null,f,r),null)),[l,h,e]}function F9(e,n){e.action=n}function Tp(e){var n=jt(),r=st;if(r!==null)return Rp(n,r,e);jt(),n=n.memoizedState,r=jt();var l=r.queue.dispatch;return r.memoizedState=e,[n,l,!1]}function No(e,n,r,l){return e={tag:e,create:r,deps:l,inst:n,next:null},n=ze.updateQueue,n===null&&(n=hs(),ze.updateQueue=n),r=n.lastEffect,r===null?n.lastEffect=e.next=e:(l=r.next,r.next=e,e.next=l,n.lastEffect=e),e}function Mp(){return jt().memoizedState}function vs(e,n,r,l){var f=sn();ze.flags|=e,f.memoizedState=No(1|n,{destroy:void 0},r,l===void 0?null:l)}function gs(e,n,r,l){var f=jt();l=l===void 0?null:l;var h=f.memoizedState.inst;st!==null&&l!==null&&a0(l,st.memoizedState.deps)?f.memoizedState=No(n,h,r,l):(ze.flags|=e,f.memoizedState=No(1|n,h,r,l))}function Dp(e,n){vs(8390656,8,e,n)}function h0(e,n){gs(2048,8,e,n)}function k9(e){ze.flags|=4;var n=ze.updateQueue;if(n===null)n=hs(),ze.updateQueue=n,n.events=[e];else{var r=n.events;r===null?n.events=[e]:r.push(e)}}function Op(e){var n=jt().memoizedState;return k9({ref:n,nextImpl:e}),function(){if((nt&2)!==0)throw Error(i(440));return n.impl.apply(void 0,arguments)}}function Np(e,n){return gs(4,2,e,n)}function Lp(e,n){return gs(4,4,e,n)}function jp(e,n){if(typeof n=="function"){e=e();var r=n(e);return function(){typeof r=="function"?r():n(null)}}if(n!=null)return e=e(),n.current=e,function(){n.current=null}}function Fp(e,n,r){r=r!=null?r.concat([e]):null,gs(4,4,jp.bind(null,n,e),r)}function p0(){}function kp(e,n){var r=jt();n=n===void 0?null:n;var l=r.memoizedState;return n!==null&&a0(n,l[1])?l[0]:(r.memoizedState=[e,n],e)}function zp(e,n){var r=jt();n=n===void 0?null:n;var l=r.memoizedState;if(n!==null&&a0(n,l[1]))return l[0];if(l=e(),Vr){qt(!0);try{e()}finally{qt(!1)}}return r.memoizedState=[l,n],l}function m0(e,n,r){return r===void 0||(Ma&1073741824)!==0&&(Ge&261930)===0?e.memoizedState=n:(e.memoizedState=r,e=Um(),ze.lanes|=e,sr|=e,r)}function Up(e,n,r,l){return An(r,n)?r:Mo.current!==null?(e=m0(e,r,l),An(e,n)||(Bt=!0),e):(Ma&42)===0||(Ma&1073741824)!==0&&(Ge&261930)===0?(Bt=!0,e.memoizedState=r):(e=Um(),ze.lanes|=e,sr|=e,n)}function Pp(e,n,r,l,f){var h=H.p;H.p=h!==0&&8>h?h:8;var E=U.T,M={};U.T=M,y0(e,!1,n,r);try{var k=f(),Q=U.S;if(Q!==null&&Q(M,k),k!==null&&typeof k=="object"&&typeof k.then=="function"){var ae=O9(k,l);ki(e,n,ae,wn(e))}else ki(e,n,l,wn(e))}catch(le){ki(e,n,{then:function(){},status:"rejected",reason:le},wn())}finally{H.p=h,E!==null&&M.types!==null&&(E.types=M.types),U.T=E}}function z9(){}function v0(e,n,r,l){if(e.tag!==5)throw Error(i(476));var f=Ip(e).queue;Pp(e,f,n,K,r===null?z9:function(){return Hp(e),r(l)})}function Ip(e){var n=e.memoizedState;if(n!==null)return n;n={memoizedState:K,baseState:K,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Da,lastRenderedState:K},next:null};var r={};return n.next={memoizedState:r,baseState:r,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Da,lastRenderedState:r},next:null},e.memoizedState=n,e=e.alternate,e!==null&&(e.memoizedState=n),n}function Hp(e){var n=Ip(e);n.next===null&&(n=e.alternate.memoizedState),ki(e,n.next.queue,{},wn())}function g0(){return Xt(Wi)}function Bp(){return jt().memoizedState}function $p(){return jt().memoizedState}function U9(e){for(var n=e.return;n!==null;){switch(n.tag){case 24:case 3:var r=wn();e=nr(r);var l=ar(n,e,r);l!==null&&(vn(l,n,r),Oi(l,n,r)),n={cache:Gc()},e.payload=n;return}n=n.return}}function P9(e,n,r){var l=wn();r={lane:l,revertLane:0,gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},ys(e)?qp(n,r):(r=Fc(e,n,r,l),r!==null&&(vn(r,e,l),Gp(r,n,l)))}function Vp(e,n,r){var l=wn();ki(e,n,r,l)}function ki(e,n,r,l){var f={lane:l,revertLane:0,gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null};if(ys(e))qp(n,f);else{var h=e.alternate;if(e.lanes===0&&(h===null||h.lanes===0)&&(h=n.lastRenderedReducer,h!==null))try{var E=n.lastRenderedState,M=h(E,r);if(f.hasEagerState=!0,f.eagerState=M,An(M,E))return Jl(e,n,f,0),ht===null&&Zl(),!1}catch{}if(r=Fc(e,n,f,l),r!==null)return vn(r,e,l),Gp(r,n,l),!0}return!1}function y0(e,n,r,l){if(l={lane:2,revertLane:X0(),gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},ys(e)){if(n)throw Error(i(479))}else n=Fc(e,r,l,2),n!==null&&vn(n,e,2)}function ys(e){var n=e.alternate;return e===ze||n!==null&&n===ze}function qp(e,n){Do=fs=!0;var r=e.pending;r===null?n.next=n:(n.next=r.next,r.next=n),e.pending=n}function Gp(e,n,r){if((r&4194048)!==0){var l=n.lanes;l&=e.pendingLanes,r|=l,n.lanes=r,Il(e,r)}}var zi={readContext:Xt,use:ps,useCallback:Tt,useContext:Tt,useEffect:Tt,useImperativeHandle:Tt,useLayoutEffect:Tt,useInsertionEffect:Tt,useMemo:Tt,useReducer:Tt,useRef:Tt,useState:Tt,useDebugValue:Tt,useDeferredValue:Tt,useTransition:Tt,useSyncExternalStore:Tt,useId:Tt,useHostTransitionStatus:Tt,useFormState:Tt,useActionState:Tt,useOptimistic:Tt,useMemoCache:Tt,useCacheRefresh:Tt};zi.useEffectEvent=Tt;var Yp={readContext:Xt,use:ps,useCallback:function(e,n){return sn().memoizedState=[e,n===void 0?null:n],e},useContext:Xt,useEffect:Dp,useImperativeHandle:function(e,n,r){r=r!=null?r.concat([e]):null,vs(4194308,4,jp.bind(null,n,e),r)},useLayoutEffect:function(e,n){return vs(4194308,4,e,n)},useInsertionEffect:function(e,n){vs(4,2,e,n)},useMemo:function(e,n){var r=sn();n=n===void 0?null:n;var l=e();if(Vr){qt(!0);try{e()}finally{qt(!1)}}return r.memoizedState=[l,n],l},useReducer:function(e,n,r){var l=sn();if(r!==void 0){var f=r(n);if(Vr){qt(!0);try{r(n)}finally{qt(!1)}}}else f=n;return l.memoizedState=l.baseState=f,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:f},l.queue=e,e=e.dispatch=P9.bind(null,ze,e),[l.memoizedState,e]},useRef:function(e){var n=sn();return e={current:e},n.memoizedState=e},useState:function(e){e=f0(e);var n=e.queue,r=Vp.bind(null,ze,n);return n.dispatch=r,[e.memoizedState,r]},useDebugValue:p0,useDeferredValue:function(e,n){var r=sn();return m0(r,e,n)},useTransition:function(){var e=f0(!1);return e=Pp.bind(null,ze,e.queue,!0,!1),sn().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,n,r){var l=ze,f=sn();if(Qe){if(r===void 0)throw Error(i(407));r=r()}else{if(r=n(),ht===null)throw Error(i(349));(Ge&127)!==0||pp(l,n,r)}f.memoizedState=r;var h={value:r,getSnapshot:n};return f.queue=h,Dp(vp.bind(null,l,h,e),[e]),l.flags|=2048,No(9,{destroy:void 0},mp.bind(null,l,h,r,n),null),r},useId:function(){var e=sn(),n=ht.identifierPrefix;if(Qe){var r=da,l=fa;r=(l&~(1<<32-tn(l)-1)).toString(32)+r,n="_"+n+"R_"+r,r=ds++,0<r&&(n+="H"+r.toString(32)),n+="_"}else r=N9++,n="_"+n+"r_"+r.toString(32)+"_";return e.memoizedState=n},useHostTransitionStatus:g0,useFormState:wp,useActionState:wp,useOptimistic:function(e){var n=sn();n.memoizedState=n.baseState=e;var r={pending:null,lanes:0,dispatch:null,lastRenderedReducer:null,lastRenderedState:null};return n.queue=r,n=y0.bind(null,ze,!0,r),r.dispatch=n,[e,n]},useMemoCache:s0,useCacheRefresh:function(){return sn().memoizedState=U9.bind(null,ze)},useEffectEvent:function(e){var n=sn(),r={impl:e};return n.memoizedState=r,function(){if((nt&2)!==0)throw Error(i(440));return r.impl.apply(void 0,arguments)}}},A0={readContext:Xt,use:ps,useCallback:kp,useContext:Xt,useEffect:h0,useImperativeHandle:Fp,useInsertionEffect:Np,useLayoutEffect:Lp,useMemo:zp,useReducer:ms,useRef:Mp,useState:function(){return ms(Da)},useDebugValue:p0,useDeferredValue:function(e,n){var r=jt();return Up(r,st.memoizedState,e,n)},useTransition:function(){var e=ms(Da)[0],n=jt().memoizedState;return[typeof e=="boolean"?e:Fi(e),n]},useSyncExternalStore:hp,useId:Bp,useHostTransitionStatus:g0,useFormState:_p,useActionState:_p,useOptimistic:function(e,n){var r=jt();return Ap(r,st,e,n)},useMemoCache:s0,useCacheRefresh:$p};A0.useEffectEvent=Op;var Qp={readContext:Xt,use:ps,useCallback:kp,useContext:Xt,useEffect:h0,useImperativeHandle:Fp,useInsertionEffect:Np,useLayoutEffect:Lp,useMemo:zp,useReducer:c0,useRef:Mp,useState:function(){return c0(Da)},useDebugValue:p0,useDeferredValue:function(e,n){var r=jt();return st===null?m0(r,e,n):Up(r,st.memoizedState,e,n)},useTransition:function(){var e=c0(Da)[0],n=jt().memoizedState;return[typeof e=="boolean"?e:Fi(e),n]},useSyncExternalStore:hp,useId:Bp,useHostTransitionStatus:g0,useFormState:Tp,useActionState:Tp,useOptimistic:function(e,n){var r=jt();return st!==null?Ap(r,st,e,n):(r.baseState=e,[e,r.queue.dispatch])},useMemoCache:s0,useCacheRefresh:$p};Qp.useEffectEvent=Op;function C0(e,n,r,l){n=e.memoizedState,r=r(l,n),r=r==null?n:p({},n,r),e.memoizedState=r,e.lanes===0&&(e.updateQueue.baseState=r)}var b0={enqueueSetState:function(e,n,r){e=e._reactInternals;var l=wn(),f=nr(l);f.payload=n,r!=null&&(f.callback=r),n=ar(e,f,l),n!==null&&(vn(n,e,l),Oi(n,e,l))},enqueueReplaceState:function(e,n,r){e=e._reactInternals;var l=wn(),f=nr(l);f.tag=1,f.payload=n,r!=null&&(f.callback=r),n=ar(e,f,l),n!==null&&(vn(n,e,l),Oi(n,e,l))},enqueueForceUpdate:function(e,n){e=e._reactInternals;var r=wn(),l=nr(r);l.tag=2,n!=null&&(l.callback=n),n=ar(e,l,r),n!==null&&(vn(n,e,r),Oi(n,e,r))}};function Kp(e,n,r,l,f,h,E){return e=e.stateNode,typeof e.shouldComponentUpdate=="function"?e.shouldComponentUpdate(l,h,E):n.prototype&&n.prototype.isPureReactComponent?!Si(r,l)||!Si(f,h):!0}function Xp(e,n,r,l){e=n.state,typeof n.componentWillReceiveProps=="function"&&n.componentWillReceiveProps(r,l),typeof n.UNSAFE_componentWillReceiveProps=="function"&&n.UNSAFE_componentWillReceiveProps(r,l),n.state!==e&&b0.enqueueReplaceState(n,n.state,null)}function qr(e,n){var r=n;if("ref"in n){r={};for(var l in n)l!=="ref"&&(r[l]=n[l])}if(e=e.defaultProps){r===n&&(r=p({},r));for(var f in e)r[f]===void 0&&(r[f]=e[f])}return r}function Zp(e){Xl(e)}function Jp(e){console.error(e)}function Wp(e){Xl(e)}function As(e,n){try{var r=e.onUncaughtError;r(n.value,{componentStack:n.stack})}catch(l){setTimeout(function(){throw l})}}function em(e,n,r){try{var l=e.onCaughtError;l(r.value,{componentStack:r.stack,errorBoundary:n.tag===1?n.stateNode:null})}catch(f){setTimeout(function(){throw f})}}function E0(e,n,r){return r=nr(r),r.tag=3,r.payload={element:null},r.callback=function(){As(e,n)},r}function tm(e){return e=nr(e),e.tag=3,e}function nm(e,n,r,l){var f=r.type.getDerivedStateFromError;if(typeof f=="function"){var h=l.value;e.payload=function(){return f(h)},e.callback=function(){em(n,r,l)}}var E=r.stateNode;E!==null&&typeof E.componentDidCatch=="function"&&(e.callback=function(){em(n,r,l),typeof f!="function"&&(ur===null?ur=new Set([this]):ur.add(this));var M=l.stack;this.componentDidCatch(l.value,{componentStack:M!==null?M:""})})}function I9(e,n,r,l,f){if(r.flags|=32768,l!==null&&typeof l=="object"&&typeof l.then=="function"){if(n=r.alternate,n!==null&&xo(n,r,f,!0),r=bn.current,r!==null){switch(r.tag){case 31:case 13:return Pn===null?Os():r.alternate===null&&Mt===0&&(Mt=3),r.flags&=-257,r.flags|=65536,r.lanes=f,l===is?r.flags|=16384:(n=r.updateQueue,n===null?r.updateQueue=new Set([l]):n.add(l),Y0(e,l,f)),!1;case 22:return r.flags|=65536,l===is?r.flags|=16384:(n=r.updateQueue,n===null?(n={transitions:null,markerInstances:null,retryQueue:new Set([l])},r.updateQueue=n):(r=n.retryQueue,r===null?n.retryQueue=new Set([l]):r.add(l)),Y0(e,l,f)),!1}throw Error(i(435,r.tag))}return Y0(e,l,f),Os(),!1}if(Qe)return n=bn.current,n!==null?((n.flags&65536)===0&&(n.flags|=256),n.flags|=65536,n.lanes=f,l!==Hc&&(e=Error(i(422),{cause:l}),_i(Fn(e,r)))):(l!==Hc&&(n=Error(i(423),{cause:l}),_i(Fn(n,r))),e=e.current.alternate,e.flags|=65536,f&=-f,e.lanes|=f,l=Fn(l,r),f=E0(e.stateNode,l,f),Jc(e,f),Mt!==4&&(Mt=2)),!1;var h=Error(i(520),{cause:l});if(h=Fn(h,r),qi===null?qi=[h]:qi.push(h),Mt!==4&&(Mt=2),n===null)return!0;l=Fn(l,r),r=n;do{switch(r.tag){case 3:return r.flags|=65536,e=f&-f,r.lanes|=e,e=E0(r.stateNode,l,e),Jc(r,e),!1;case 1:if(n=r.type,h=r.stateNode,(r.flags&128)===0&&(typeof n.getDerivedStateFromError=="function"||h!==null&&typeof h.componentDidCatch=="function"&&(ur===null||!ur.has(h))))return r.flags|=65536,f&=-f,r.lanes|=f,f=tm(f),nm(f,e,r,l),Jc(r,f),!1}r=r.return}while(r!==null);return!1}var S0=Error(i(461)),Bt=!1;function Zt(e,n,r,l){n.child=e===null?ip(n,null,r,l):$r(n,e.child,r,l)}function am(e,n,r,l,f){r=r.render;var h=n.ref;if("ref"in l){var E={};for(var M in l)M!=="ref"&&(E[M]=l[M])}else E=l;return Pr(n),l=r0(e,n,r,E,h,f),M=o0(),e!==null&&!Bt?(i0(e,n,f),Oa(e,n,f)):(Qe&&M&&Pc(n),n.flags|=1,Zt(e,n,l,f),n.child)}function rm(e,n,r,l,f){if(e===null){var h=r.type;return typeof h=="function"&&!kc(h)&&h.defaultProps===void 0&&r.compare===null?(n.tag=15,n.type=h,om(e,n,h,l,f)):(e=es(r.type,null,l,n,n.mode,f),e.ref=n.ref,e.return=n,n.child=e)}if(h=e.child,!O0(e,f)){var E=h.memoizedProps;if(r=r.compare,r=r!==null?r:Si,r(E,l)&&e.ref===n.ref)return Oa(e,n,f)}return n.flags|=1,e=wa(h,l),e.ref=n.ref,e.return=n,n.child=e}function om(e,n,r,l,f){if(e!==null){var h=e.memoizedProps;if(Si(h,l)&&e.ref===n.ref)if(Bt=!1,n.pendingProps=l=h,O0(e,f))(e.flags&131072)!==0&&(Bt=!0);else return n.lanes=e.lanes,Oa(e,n,f)}return x0(e,n,r,l,f)}function im(e,n,r,l){var f=l.children,h=e!==null?e.memoizedState:null;if(e===null&&n.stateNode===null&&(n.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),l.mode==="hidden"){if((n.flags&128)!==0){if(h=h!==null?h.baseLanes|r:r,e!==null){for(l=n.child=e.child,f=0;l!==null;)f=f|l.lanes|l.childLanes,l=l.sibling;l=f&~h}else l=0,n.child=null;return lm(e,n,h,r,l)}if((r&536870912)!==0)n.memoizedState={baseLanes:0,cachePool:null},e!==null&&rs(n,h!==null?h.cachePool:null),h!==null?up(n,h):e0(),cp(n);else return l=n.lanes=536870912,lm(e,n,h!==null?h.baseLanes|r:r,r,l)}else h!==null?(rs(n,h.cachePool),up(n,h),or(),n.memoizedState=null):(e!==null&&rs(n,null),e0(),or());return Zt(e,n,f,r),n.child}function Ui(e,n){return e!==null&&e.tag===22||n.stateNode!==null||(n.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),n.sibling}function lm(e,n,r,l,f){var h=Qc();return h=h===null?null:{parent:It._currentValue,pool:h},n.memoizedState={baseLanes:r,cachePool:h},e!==null&&rs(n,null),e0(),cp(n),e!==null&&xo(e,n,l,!0),n.childLanes=f,null}function Cs(e,n){return n=Es({mode:n.mode,children:n.children},e.mode),n.ref=e.ref,e.child=n,n.return=e,n}function sm(e,n,r){return $r(n,e.child,null,r),e=Cs(n,n.pendingProps),e.flags|=2,En(n),n.memoizedState=null,e}function H9(e,n,r){var l=n.pendingProps,f=(n.flags&128)!==0;if(n.flags&=-129,e===null){if(Qe){if(l.mode==="hidden")return e=Cs(n,l),n.lanes=536870912,Ui(null,e);if(n0(n),(e=Et)?(e=Cv(e,Un),e=e!==null&&e.data==="&"?e:null,e!==null&&(n.memoizedState={dehydrated:e,treeContext:Za!==null?{id:fa,overflow:da}:null,retryLane:536870912,hydrationErrors:null},r=qh(e),r.return=n,n.child=r,Kt=n,Et=null)):e=null,e===null)throw Wa(n);return n.lanes=536870912,null}return Cs(n,l)}var h=e.memoizedState;if(h!==null){var E=h.dehydrated;if(n0(n),f)if(n.flags&256)n.flags&=-257,n=sm(e,n,r);else if(n.memoizedState!==null)n.child=e.child,n.flags|=128,n=null;else throw Error(i(558));else if(Bt||xo(e,n,r,!1),f=(r&e.childLanes)!==0,Bt||f){if(l=ht,l!==null&&(E=z(l,r),E!==0&&E!==h.retryLane))throw h.retryLane=E,Fr(e,E),vn(l,e,E),S0;Os(),n=sm(e,n,r)}else e=h.treeContext,Et=In(E.nextSibling),Kt=n,Qe=!0,Ja=null,Un=!1,e!==null&&Qh(n,e),n=Cs(n,l),n.flags|=4096;return n}return e=wa(e.child,{mode:l.mode,children:l.children}),e.ref=n.ref,n.child=e,e.return=n,e}function bs(e,n){var r=n.ref;if(r===null)e!==null&&e.ref!==null&&(n.flags|=4194816);else{if(typeof r!="function"&&typeof r!="object")throw Error(i(284));(e===null||e.ref!==r)&&(n.flags|=4194816)}}function x0(e,n,r,l,f){return Pr(n),r=r0(e,n,r,l,void 0,f),l=o0(),e!==null&&!Bt?(i0(e,n,f),Oa(e,n,f)):(Qe&&l&&Pc(n),n.flags|=1,Zt(e,n,r,f),n.child)}function um(e,n,r,l,f,h){return Pr(n),n.updateQueue=null,r=dp(n,l,r,f),fp(e),l=o0(),e!==null&&!Bt?(i0(e,n,h),Oa(e,n,h)):(Qe&&l&&Pc(n),n.flags|=1,Zt(e,n,r,h),n.child)}function cm(e,n,r,l,f){if(Pr(n),n.stateNode===null){var h=Co,E=r.contextType;typeof E=="object"&&E!==null&&(h=Xt(E)),h=new r(l,h),n.memoizedState=h.state!==null&&h.state!==void 0?h.state:null,h.updater=b0,n.stateNode=h,h._reactInternals=n,h=n.stateNode,h.props=l,h.state=n.memoizedState,h.refs={},Xc(n),E=r.contextType,h.context=typeof E=="object"&&E!==null?Xt(E):Co,h.state=n.memoizedState,E=r.getDerivedStateFromProps,typeof E=="function"&&(C0(n,r,E,l),h.state=n.memoizedState),typeof r.getDerivedStateFromProps=="function"||typeof h.getSnapshotBeforeUpdate=="function"||typeof h.UNSAFE_componentWillMount!="function"&&typeof h.componentWillMount!="function"||(E=h.state,typeof h.componentWillMount=="function"&&h.componentWillMount(),typeof h.UNSAFE_componentWillMount=="function"&&h.UNSAFE_componentWillMount(),E!==h.state&&b0.enqueueReplaceState(h,h.state,null),Li(n,l,h,f),Ni(),h.state=n.memoizedState),typeof h.componentDidMount=="function"&&(n.flags|=4194308),l=!0}else if(e===null){h=n.stateNode;var M=n.memoizedProps,k=qr(r,M);h.props=k;var Q=h.context,ae=r.contextType;E=Co,typeof ae=="object"&&ae!==null&&(E=Xt(ae));var le=r.getDerivedStateFromProps;ae=typeof le=="function"||typeof h.getSnapshotBeforeUpdate=="function",M=n.pendingProps!==M,ae||typeof h.UNSAFE_componentWillReceiveProps!="function"&&typeof h.componentWillReceiveProps!="function"||(M||Q!==E)&&Xp(n,h,l,E),tr=!1;var Z=n.memoizedState;h.state=Z,Li(n,l,h,f),Ni(),Q=n.memoizedState,M||Z!==Q||tr?(typeof le=="function"&&(C0(n,r,le,l),Q=n.memoizedState),(k=tr||Kp(n,r,k,l,Z,Q,E))?(ae||typeof h.UNSAFE_componentWillMount!="function"&&typeof h.componentWillMount!="function"||(typeof h.componentWillMount=="function"&&h.componentWillMount(),typeof h.UNSAFE_componentWillMount=="function"&&h.UNSAFE_componentWillMount()),typeof h.componentDidMount=="function"&&(n.flags|=4194308)):(typeof h.componentDidMount=="function"&&(n.flags|=4194308),n.memoizedProps=l,n.memoizedState=Q),h.props=l,h.state=Q,h.context=E,l=k):(typeof h.componentDidMount=="function"&&(n.flags|=4194308),l=!1)}else{h=n.stateNode,Zc(e,n),E=n.memoizedProps,ae=qr(r,E),h.props=ae,le=n.pendingProps,Z=h.context,Q=r.contextType,k=Co,typeof Q=="object"&&Q!==null&&(k=Xt(Q)),M=r.getDerivedStateFromProps,(Q=typeof M=="function"||typeof h.getSnapshotBeforeUpdate=="function")||typeof h.UNSAFE_componentWillReceiveProps!="function"&&typeof h.componentWillReceiveProps!="function"||(E!==le||Z!==k)&&Xp(n,h,l,k),tr=!1,Z=n.memoizedState,h.state=Z,Li(n,l,h,f),Ni();var ee=n.memoizedState;E!==le||Z!==ee||tr||e!==null&&e.dependencies!==null&&ns(e.dependencies)?(typeof M=="function"&&(C0(n,r,M,l),ee=n.memoizedState),(ae=tr||Kp(n,r,ae,l,Z,ee,k)||e!==null&&e.dependencies!==null&&ns(e.dependencies))?(Q||typeof h.UNSAFE_componentWillUpdate!="function"&&typeof h.componentWillUpdate!="function"||(typeof h.componentWillUpdate=="function"&&h.componentWillUpdate(l,ee,k),typeof h.UNSAFE_componentWillUpdate=="function"&&h.UNSAFE_componentWillUpdate(l,ee,k)),typeof h.componentDidUpdate=="function"&&(n.flags|=4),typeof h.getSnapshotBeforeUpdate=="function"&&(n.flags|=1024)):(typeof h.componentDidUpdate!="function"||E===e.memoizedProps&&Z===e.memoizedState||(n.flags|=4),typeof h.getSnapshotBeforeUpdate!="function"||E===e.memoizedProps&&Z===e.memoizedState||(n.flags|=1024),n.memoizedProps=l,n.memoizedState=ee),h.props=l,h.state=ee,h.context=k,l=ae):(typeof h.componentDidUpdate!="function"||E===e.memoizedProps&&Z===e.memoizedState||(n.flags|=4),typeof h.getSnapshotBeforeUpdate!="function"||E===e.memoizedProps&&Z===e.memoizedState||(n.flags|=1024),l=!1)}return h=l,bs(e,n),l=(n.flags&128)!==0,h||l?(h=n.stateNode,r=l&&typeof r.getDerivedStateFromError!="function"?null:h.render(),n.flags|=1,e!==null&&l?(n.child=$r(n,e.child,null,f),n.child=$r(n,null,r,f)):Zt(e,n,r,f),n.memoizedState=h.state,e=n.child):e=Oa(e,n,f),e}function fm(e,n,r,l){return zr(),n.flags|=256,Zt(e,n,r,l),n.child}var w0={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function _0(e){return{baseLanes:e,cachePool:ep()}}function R0(e,n,r){return e=e!==null?e.childLanes&~r:0,n&&(e|=xn),e}function dm(e,n,r){var l=n.pendingProps,f=!1,h=(n.flags&128)!==0,E;if((E=h)||(E=e!==null&&e.memoizedState===null?!1:(Lt.current&2)!==0),E&&(f=!0,n.flags&=-129),E=(n.flags&32)!==0,n.flags&=-33,e===null){if(Qe){if(f?rr(n):or(),(e=Et)?(e=Cv(e,Un),e=e!==null&&e.data!=="&"?e:null,e!==null&&(n.memoizedState={dehydrated:e,treeContext:Za!==null?{id:fa,overflow:da}:null,retryLane:536870912,hydrationErrors:null},r=qh(e),r.return=n,n.child=r,Kt=n,Et=null)):e=null,e===null)throw Wa(n);return u2(e)?n.lanes=32:n.lanes=536870912,null}var M=l.children;return l=l.fallback,f?(or(),f=n.mode,M=Es({mode:"hidden",children:M},f),l=kr(l,f,r,null),M.return=n,l.return=n,M.sibling=l,n.child=M,l=n.child,l.memoizedState=_0(r),l.childLanes=R0(e,E,r),n.memoizedState=w0,Ui(null,l)):(rr(n),T0(n,M))}var k=e.memoizedState;if(k!==null&&(M=k.dehydrated,M!==null)){if(h)n.flags&256?(rr(n),n.flags&=-257,n=M0(e,n,r)):n.memoizedState!==null?(or(),n.child=e.child,n.flags|=128,n=null):(or(),M=l.fallback,f=n.mode,l=Es({mode:"visible",children:l.children},f),M=kr(M,f,r,null),M.flags|=2,l.return=n,M.return=n,l.sibling=M,n.child=l,$r(n,e.child,null,r),l=n.child,l.memoizedState=_0(r),l.childLanes=R0(e,E,r),n.memoizedState=w0,n=Ui(null,l));else if(rr(n),u2(M)){if(E=M.nextSibling&&M.nextSibling.dataset,E)var Q=E.dgst;E=Q,l=Error(i(419)),l.stack="",l.digest=E,_i({value:l,source:null,stack:null}),n=M0(e,n,r)}else if(Bt||xo(e,n,r,!1),E=(r&e.childLanes)!==0,Bt||E){if(E=ht,E!==null&&(l=z(E,r),l!==0&&l!==k.retryLane))throw k.retryLane=l,Fr(e,l),vn(E,e,l),S0;s2(M)||Os(),n=M0(e,n,r)}else s2(M)?(n.flags|=192,n.child=e.child,n=null):(e=k.treeContext,Et=In(M.nextSibling),Kt=n,Qe=!0,Ja=null,Un=!1,e!==null&&Qh(n,e),n=T0(n,l.children),n.flags|=4096);return n}return f?(or(),M=l.fallback,f=n.mode,k=e.child,Q=k.sibling,l=wa(k,{mode:"hidden",children:l.children}),l.subtreeFlags=k.subtreeFlags&65011712,Q!==null?M=wa(Q,M):(M=kr(M,f,r,null),M.flags|=2),M.return=n,l.return=n,l.sibling=M,n.child=l,Ui(null,l),l=n.child,M=e.child.memoizedState,M===null?M=_0(r):(f=M.cachePool,f!==null?(k=It._currentValue,f=f.parent!==k?{parent:k,pool:k}:f):f=ep(),M={baseLanes:M.baseLanes|r,cachePool:f}),l.memoizedState=M,l.childLanes=R0(e,E,r),n.memoizedState=w0,Ui(e.child,l)):(rr(n),r=e.child,e=r.sibling,r=wa(r,{mode:"visible",children:l.children}),r.return=n,r.sibling=null,e!==null&&(E=n.deletions,E===null?(n.deletions=[e],n.flags|=16):E.push(e)),n.child=r,n.memoizedState=null,r)}function T0(e,n){return n=Es({mode:"visible",children:n},e.mode),n.return=e,e.child=n}function Es(e,n){return e=Cn(22,e,null,n),e.lanes=0,e}function M0(e,n,r){return $r(n,e.child,null,r),e=T0(n,n.pendingProps.children),e.flags|=2,n.memoizedState=null,e}function hm(e,n,r){e.lanes|=n;var l=e.alternate;l!==null&&(l.lanes|=n),Vc(e.return,n,r)}function D0(e,n,r,l,f,h){var E=e.memoizedState;E===null?e.memoizedState={isBackwards:n,rendering:null,renderingStartTime:0,last:l,tail:r,tailMode:f,treeForkCount:h}:(E.isBackwards=n,E.rendering=null,E.renderingStartTime=0,E.last=l,E.tail=r,E.tailMode=f,E.treeForkCount=h)}function pm(e,n,r){var l=n.pendingProps,f=l.revealOrder,h=l.tail;l=l.children;var E=Lt.current,M=(E&2)!==0;if(M?(E=E&1|2,n.flags|=128):E&=1,ne(Lt,E),Zt(e,n,l,r),l=Qe?wi:0,!M&&e!==null&&(e.flags&128)!==0)e:for(e=n.child;e!==null;){if(e.tag===13)e.memoizedState!==null&&hm(e,r,n);else if(e.tag===19)hm(e,r,n);else if(e.child!==null){e.child.return=e,e=e.child;continue}if(e===n)break e;for(;e.sibling===null;){if(e.return===null||e.return===n)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}switch(f){case"forwards":for(r=n.child,f=null;r!==null;)e=r.alternate,e!==null&&cs(e)===null&&(f=r),r=r.sibling;r=f,r===null?(f=n.child,n.child=null):(f=r.sibling,r.sibling=null),D0(n,!1,f,r,h,l);break;case"backwards":case"unstable_legacy-backwards":for(r=null,f=n.child,n.child=null;f!==null;){if(e=f.alternate,e!==null&&cs(e)===null){n.child=f;break}e=f.sibling,f.sibling=r,r=f,f=e}D0(n,!0,r,null,h,l);break;case"together":D0(n,!1,null,null,void 0,l);break;default:n.memoizedState=null}return n.child}function Oa(e,n,r){if(e!==null&&(n.dependencies=e.dependencies),sr|=n.lanes,(r&n.childLanes)===0)if(e!==null){if(xo(e,n,r,!1),(r&n.childLanes)===0)return null}else return null;if(e!==null&&n.child!==e.child)throw Error(i(153));if(n.child!==null){for(e=n.child,r=wa(e,e.pendingProps),n.child=r,r.return=n;e.sibling!==null;)e=e.sibling,r=r.sibling=wa(e,e.pendingProps),r.return=n;r.sibling=null}return n.child}function O0(e,n){return(e.lanes&n)!==0?!0:(e=e.dependencies,!!(e!==null&&ns(e)))}function B9(e,n,r){switch(n.tag){case 3:q(n,n.stateNode.containerInfo),er(n,It,e.memoizedState.cache),zr();break;case 27:case 5:lt(n);break;case 4:q(n,n.stateNode.containerInfo);break;case 10:er(n,n.type,n.memoizedProps.value);break;case 31:if(n.memoizedState!==null)return n.flags|=128,n0(n),null;break;case 13:var l=n.memoizedState;if(l!==null)return l.dehydrated!==null?(rr(n),n.flags|=128,null):(r&n.child.childLanes)!==0?dm(e,n,r):(rr(n),e=Oa(e,n,r),e!==null?e.sibling:null);rr(n);break;case 19:var f=(e.flags&128)!==0;if(l=(r&n.childLanes)!==0,l||(xo(e,n,r,!1),l=(r&n.childLanes)!==0),f){if(l)return pm(e,n,r);n.flags|=128}if(f=n.memoizedState,f!==null&&(f.rendering=null,f.tail=null,f.lastEffect=null),ne(Lt,Lt.current),l)break;return null;case 22:return n.lanes=0,im(e,n,r,n.pendingProps);case 24:er(n,It,e.memoizedState.cache)}return Oa(e,n,r)}function mm(e,n,r){if(e!==null)if(e.memoizedProps!==n.pendingProps)Bt=!0;else{if(!O0(e,r)&&(n.flags&128)===0)return Bt=!1,B9(e,n,r);Bt=(e.flags&131072)!==0}else Bt=!1,Qe&&(n.flags&1048576)!==0&&Yh(n,wi,n.index);switch(n.lanes=0,n.tag){case 16:e:{var l=n.pendingProps;if(e=Hr(n.elementType),n.type=e,typeof e=="function")kc(e)?(l=qr(e,l),n.tag=1,n=cm(null,n,e,l,r)):(n.tag=0,n=x0(null,n,e,l,r));else{if(e!=null){var f=e.$$typeof;if(f===_){n.tag=11,n=am(null,n,e,l,r);break e}else if(f===F){n.tag=14,n=rm(null,n,e,l,r);break e}}throw n=J(e)||e,Error(i(306,n,""))}}return n;case 0:return x0(e,n,n.type,n.pendingProps,r);case 1:return l=n.type,f=qr(l,n.pendingProps),cm(e,n,l,f,r);case 3:e:{if(q(n,n.stateNode.containerInfo),e===null)throw Error(i(387));l=n.pendingProps;var h=n.memoizedState;f=h.element,Zc(e,n),Li(n,l,null,r);var E=n.memoizedState;if(l=E.cache,er(n,It,l),l!==h.cache&&qc(n,[It],r,!0),Ni(),l=E.element,h.isDehydrated)if(h={element:l,isDehydrated:!1,cache:E.cache},n.updateQueue.baseState=h,n.memoizedState=h,n.flags&256){n=fm(e,n,l,r);break e}else if(l!==f){f=Fn(Error(i(424)),n),_i(f),n=fm(e,n,l,r);break e}else for(e=n.stateNode.containerInfo,e.nodeType===9?e=e.body:e=e.nodeName==="HTML"?e.ownerDocument.body:e,Et=In(e.firstChild),Kt=n,Qe=!0,Ja=null,Un=!0,r=ip(n,null,l,r),n.child=r;r;)r.flags=r.flags&-3|4096,r=r.sibling;else{if(zr(),l===f){n=Oa(e,n,r);break e}Zt(e,n,l,r)}n=n.child}return n;case 26:return bs(e,n),e===null?(r=_v(n.type,null,n.pendingProps,null))?n.memoizedState=r:Qe||(r=n.type,e=n.pendingProps,l=Us(Se.current).createElement(r),l[Ce]=n,l[be]=e,Jt(l,r,e),vt(l),n.stateNode=l):n.memoizedState=_v(n.type,e.memoizedProps,n.pendingProps,e.memoizedState),null;case 27:return lt(n),e===null&&Qe&&(l=n.stateNode=Sv(n.type,n.pendingProps,Se.current),Kt=n,Un=!0,f=Et,hr(n.type)?(c2=f,Et=In(l.firstChild)):Et=f),Zt(e,n,n.pendingProps.children,r),bs(e,n),e===null&&(n.flags|=4194304),n.child;case 5:return e===null&&Qe&&((f=l=Et)&&(l=y4(l,n.type,n.pendingProps,Un),l!==null?(n.stateNode=l,Kt=n,Et=In(l.firstChild),Un=!1,f=!0):f=!1),f||Wa(n)),lt(n),f=n.type,h=n.pendingProps,E=e!==null?e.memoizedProps:null,l=h.children,o2(f,h)?l=null:E!==null&&o2(f,E)&&(n.flags|=32),n.memoizedState!==null&&(f=r0(e,n,L9,null,null,r),Wi._currentValue=f),bs(e,n),Zt(e,n,l,r),n.child;case 6:return e===null&&Qe&&((e=r=Et)&&(r=A4(r,n.pendingProps,Un),r!==null?(n.stateNode=r,Kt=n,Et=null,e=!0):e=!1),e||Wa(n)),null;case 13:return dm(e,n,r);case 4:return q(n,n.stateNode.containerInfo),l=n.pendingProps,e===null?n.child=$r(n,null,l,r):Zt(e,n,l,r),n.child;case 11:return am(e,n,n.type,n.pendingProps,r);case 7:return Zt(e,n,n.pendingProps,r),n.child;case 8:return Zt(e,n,n.pendingProps.children,r),n.child;case 12:return Zt(e,n,n.pendingProps.children,r),n.child;case 10:return l=n.pendingProps,er(n,n.type,l.value),Zt(e,n,l.children,r),n.child;case 9:return f=n.type._context,l=n.pendingProps.children,Pr(n),f=Xt(f),l=l(f),n.flags|=1,Zt(e,n,l,r),n.child;case 14:return rm(e,n,n.type,n.pendingProps,r);case 15:return om(e,n,n.type,n.pendingProps,r);case 19:return pm(e,n,r);case 31:return H9(e,n,r);case 22:return im(e,n,r,n.pendingProps);case 24:return Pr(n),l=Xt(It),e===null?(f=Qc(),f===null&&(f=ht,h=Gc(),f.pooledCache=h,h.refCount++,h!==null&&(f.pooledCacheLanes|=r),f=h),n.memoizedState={parent:l,cache:f},Xc(n),er(n,It,f)):((e.lanes&r)!==0&&(Zc(e,n),Li(n,null,null,r),Ni()),f=e.memoizedState,h=n.memoizedState,f.parent!==l?(f={parent:l,cache:l},n.memoizedState=f,n.lanes===0&&(n.memoizedState=n.updateQueue.baseState=f),er(n,It,l)):(l=h.cache,er(n,It,l),l!==f.cache&&qc(n,[It],r,!0))),Zt(e,n,n.pendingProps.children,r),n.child;case 29:throw n.pendingProps}throw Error(i(156,n.tag))}function Na(e){e.flags|=4}function N0(e,n,r,l,f){if((n=(e.mode&32)!==0)&&(n=!1),n){if(e.flags|=16777216,(f&335544128)===f)if(e.stateNode.complete)e.flags|=8192;else if(Bm())e.flags|=8192;else throw Br=is,Kc}else e.flags&=-16777217}function vm(e,n){if(n.type!=="stylesheet"||(n.state.loading&4)!==0)e.flags&=-16777217;else if(e.flags|=16777216,!Ov(n))if(Bm())e.flags|=8192;else throw Br=is,Kc}function Ss(e,n){n!==null&&(e.flags|=4),e.flags&16384&&(n=e.tag!==22?mi():536870912,e.lanes|=n,ko|=n)}function Pi(e,n){if(!Qe)switch(e.tailMode){case"hidden":n=e.tail;for(var r=null;n!==null;)n.alternate!==null&&(r=n),n=n.sibling;r===null?e.tail=null:r.sibling=null;break;case"collapsed":r=e.tail;for(var l=null;r!==null;)r.alternate!==null&&(l=r),r=r.sibling;l===null?n||e.tail===null?e.tail=null:e.tail.sibling=null:l.sibling=null}}function St(e){var n=e.alternate!==null&&e.alternate.child===e.child,r=0,l=0;if(n)for(var f=e.child;f!==null;)r|=f.lanes|f.childLanes,l|=f.subtreeFlags&65011712,l|=f.flags&65011712,f.return=e,f=f.sibling;else for(f=e.child;f!==null;)r|=f.lanes|f.childLanes,l|=f.subtreeFlags,l|=f.flags,f.return=e,f=f.sibling;return e.subtreeFlags|=l,e.childLanes=r,n}function $9(e,n,r){var l=n.pendingProps;switch(Ic(n),n.tag){case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return St(n),null;case 1:return St(n),null;case 3:return r=n.stateNode,l=null,e!==null&&(l=e.memoizedState.cache),n.memoizedState.cache!==l&&(n.flags|=2048),Ta(It),we(),r.pendingContext&&(r.context=r.pendingContext,r.pendingContext=null),(e===null||e.child===null)&&(So(n)?Na(n):e===null||e.memoizedState.isDehydrated&&(n.flags&256)===0||(n.flags|=1024,Bc())),St(n),null;case 26:var f=n.type,h=n.memoizedState;return e===null?(Na(n),h!==null?(St(n),vm(n,h)):(St(n),N0(n,f,null,l,r))):h?h!==e.memoizedState?(Na(n),St(n),vm(n,h)):(St(n),n.flags&=-16777217):(e=e.memoizedProps,e!==l&&Na(n),St(n),N0(n,f,e,l,r)),null;case 27:if(Xe(n),r=Se.current,f=n.type,e!==null&&n.stateNode!=null)e.memoizedProps!==l&&Na(n);else{if(!l){if(n.stateNode===null)throw Error(i(166));return St(n),null}e=ie.current,So(n)?Kh(n):(e=Sv(f,l,r),n.stateNode=e,Na(n))}return St(n),null;case 5:if(Xe(n),f=n.type,e!==null&&n.stateNode!=null)e.memoizedProps!==l&&Na(n);else{if(!l){if(n.stateNode===null)throw Error(i(166));return St(n),null}if(h=ie.current,So(n))Kh(n);else{var E=Us(Se.current);switch(h){case 1:h=E.createElementNS("http://www.w3.org/2000/svg",f);break;case 2:h=E.createElementNS("http://www.w3.org/1998/Math/MathML",f);break;default:switch(f){case"svg":h=E.createElementNS("http://www.w3.org/2000/svg",f);break;case"math":h=E.createElementNS("http://www.w3.org/1998/Math/MathML",f);break;case"script":h=E.createElement("div"),h.innerHTML="<script><\/script>",h=h.removeChild(h.firstChild);break;case"select":h=typeof l.is=="string"?E.createElement("select",{is:l.is}):E.createElement("select"),l.multiple?h.multiple=!0:l.size&&(h.size=l.size);break;default:h=typeof l.is=="string"?E.createElement(f,{is:l.is}):E.createElement(f)}}h[Ce]=n,h[be]=l;e:for(E=n.child;E!==null;){if(E.tag===5||E.tag===6)h.appendChild(E.stateNode);else if(E.tag!==4&&E.tag!==27&&E.child!==null){E.child.return=E,E=E.child;continue}if(E===n)break e;for(;E.sibling===null;){if(E.return===null||E.return===n)break e;E=E.return}E.sibling.return=E.return,E=E.sibling}n.stateNode=h;e:switch(Jt(h,f,l),f){case"button":case"input":case"select":case"textarea":l=!!l.autoFocus;break e;case"img":l=!0;break e;default:l=!1}l&&Na(n)}}return St(n),N0(n,n.type,e===null?null:e.memoizedProps,n.pendingProps,r),null;case 6:if(e&&n.stateNode!=null)e.memoizedProps!==l&&Na(n);else{if(typeof l!="string"&&n.stateNode===null)throw Error(i(166));if(e=Se.current,So(n)){if(e=n.stateNode,r=n.memoizedProps,l=null,f=Kt,f!==null)switch(f.tag){case 27:case 5:l=f.memoizedProps}e[Ce]=n,e=!!(e.nodeValue===r||l!==null&&l.suppressHydrationWarning===!0||dv(e.nodeValue,r)),e||Wa(n,!0)}else e=Us(e).createTextNode(l),e[Ce]=n,n.stateNode=e}return St(n),null;case 31:if(r=n.memoizedState,e===null||e.memoizedState!==null){if(l=So(n),r!==null){if(e===null){if(!l)throw Error(i(318));if(e=n.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(i(557));e[Ce]=n}else zr(),(n.flags&128)===0&&(n.memoizedState=null),n.flags|=4;St(n),e=!1}else r=Bc(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=r),e=!0;if(!e)return n.flags&256?(En(n),n):(En(n),null);if((n.flags&128)!==0)throw Error(i(558))}return St(n),null;case 13:if(l=n.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(f=So(n),l!==null&&l.dehydrated!==null){if(e===null){if(!f)throw Error(i(318));if(f=n.memoizedState,f=f!==null?f.dehydrated:null,!f)throw Error(i(317));f[Ce]=n}else zr(),(n.flags&128)===0&&(n.memoizedState=null),n.flags|=4;St(n),f=!1}else f=Bc(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=f),f=!0;if(!f)return n.flags&256?(En(n),n):(En(n),null)}return En(n),(n.flags&128)!==0?(n.lanes=r,n):(r=l!==null,e=e!==null&&e.memoizedState!==null,r&&(l=n.child,f=null,l.alternate!==null&&l.alternate.memoizedState!==null&&l.alternate.memoizedState.cachePool!==null&&(f=l.alternate.memoizedState.cachePool.pool),h=null,l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(h=l.memoizedState.cachePool.pool),h!==f&&(l.flags|=2048)),r!==e&&r&&(n.child.flags|=8192),Ss(n,n.updateQueue),St(n),null);case 4:return we(),e===null&&e2(n.stateNode.containerInfo),St(n),null;case 10:return Ta(n.type),St(n),null;case 19:if($(Lt),l=n.memoizedState,l===null)return St(n),null;if(f=(n.flags&128)!==0,h=l.rendering,h===null)if(f)Pi(l,!1);else{if(Mt!==0||e!==null&&(e.flags&128)!==0)for(e=n.child;e!==null;){if(h=cs(e),h!==null){for(n.flags|=128,Pi(l,!1),e=h.updateQueue,n.updateQueue=e,Ss(n,e),n.subtreeFlags=0,e=r,r=n.child;r!==null;)Vh(r,e),r=r.sibling;return ne(Lt,Lt.current&1|2),Qe&&_a(n,l.treeForkCount),n.child}e=e.sibling}l.tail!==null&&kt()>Ts&&(n.flags|=128,f=!0,Pi(l,!1),n.lanes=4194304)}else{if(!f)if(e=cs(h),e!==null){if(n.flags|=128,f=!0,e=e.updateQueue,n.updateQueue=e,Ss(n,e),Pi(l,!0),l.tail===null&&l.tailMode==="hidden"&&!h.alternate&&!Qe)return St(n),null}else 2*kt()-l.renderingStartTime>Ts&&r!==536870912&&(n.flags|=128,f=!0,Pi(l,!1),n.lanes=4194304);l.isBackwards?(h.sibling=n.child,n.child=h):(e=l.last,e!==null?e.sibling=h:n.child=h,l.last=h)}return l.tail!==null?(e=l.tail,l.rendering=e,l.tail=e.sibling,l.renderingStartTime=kt(),e.sibling=null,r=Lt.current,ne(Lt,f?r&1|2:r&1),Qe&&_a(n,l.treeForkCount),e):(St(n),null);case 22:case 23:return En(n),t0(),l=n.memoizedState!==null,e!==null?e.memoizedState!==null!==l&&(n.flags|=8192):l&&(n.flags|=8192),l?(r&536870912)!==0&&(n.flags&128)===0&&(St(n),n.subtreeFlags&6&&(n.flags|=8192)):St(n),r=n.updateQueue,r!==null&&Ss(n,r.retryQueue),r=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(r=e.memoizedState.cachePool.pool),l=null,n.memoizedState!==null&&n.memoizedState.cachePool!==null&&(l=n.memoizedState.cachePool.pool),l!==r&&(n.flags|=2048),e!==null&&$(Ir),null;case 24:return r=null,e!==null&&(r=e.memoizedState.cache),n.memoizedState.cache!==r&&(n.flags|=2048),Ta(It),St(n),null;case 25:return null;case 30:return null}throw Error(i(156,n.tag))}function V9(e,n){switch(Ic(n),n.tag){case 1:return e=n.flags,e&65536?(n.flags=e&-65537|128,n):null;case 3:return Ta(It),we(),e=n.flags,(e&65536)!==0&&(e&128)===0?(n.flags=e&-65537|128,n):null;case 26:case 27:case 5:return Xe(n),null;case 31:if(n.memoizedState!==null){if(En(n),n.alternate===null)throw Error(i(340));zr()}return e=n.flags,e&65536?(n.flags=e&-65537|128,n):null;case 13:if(En(n),e=n.memoizedState,e!==null&&e.dehydrated!==null){if(n.alternate===null)throw Error(i(340));zr()}return e=n.flags,e&65536?(n.flags=e&-65537|128,n):null;case 19:return $(Lt),null;case 4:return we(),null;case 10:return Ta(n.type),null;case 22:case 23:return En(n),t0(),e!==null&&$(Ir),e=n.flags,e&65536?(n.flags=e&-65537|128,n):null;case 24:return Ta(It),null;case 25:return null;default:return null}}function gm(e,n){switch(Ic(n),n.tag){case 3:Ta(It),we();break;case 26:case 27:case 5:Xe(n);break;case 4:we();break;case 31:n.memoizedState!==null&&En(n);break;case 13:En(n);break;case 19:$(Lt);break;case 10:Ta(n.type);break;case 22:case 23:En(n),t0(),e!==null&&$(Ir);break;case 24:Ta(It)}}function Ii(e,n){try{var r=n.updateQueue,l=r!==null?r.lastEffect:null;if(l!==null){var f=l.next;r=f;do{if((r.tag&e)===e){l=void 0;var h=r.create,E=r.inst;l=h(),E.destroy=l}r=r.next}while(r!==f)}}catch(M){it(n,n.return,M)}}function ir(e,n,r){try{var l=n.updateQueue,f=l!==null?l.lastEffect:null;if(f!==null){var h=f.next;l=h;do{if((l.tag&e)===e){var E=l.inst,M=E.destroy;if(M!==void 0){E.destroy=void 0,f=n;var k=r,Q=M;try{Q()}catch(ae){it(f,k,ae)}}}l=l.next}while(l!==h)}}catch(ae){it(n,n.return,ae)}}function ym(e){var n=e.updateQueue;if(n!==null){var r=e.stateNode;try{sp(n,r)}catch(l){it(e,e.return,l)}}}function Am(e,n,r){r.props=qr(e.type,e.memoizedProps),r.state=e.memoizedState;try{r.componentWillUnmount()}catch(l){it(e,n,l)}}function Hi(e,n){try{var r=e.ref;if(r!==null){switch(e.tag){case 26:case 27:case 5:var l=e.stateNode;break;case 30:l=e.stateNode;break;default:l=e.stateNode}typeof r=="function"?e.refCleanup=r(l):r.current=l}}catch(f){it(e,n,f)}}function ha(e,n){var r=e.ref,l=e.refCleanup;if(r!==null)if(typeof l=="function")try{l()}catch(f){it(e,n,f)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof r=="function")try{r(null)}catch(f){it(e,n,f)}else r.current=null}function Cm(e){var n=e.type,r=e.memoizedProps,l=e.stateNode;try{e:switch(n){case"button":case"input":case"select":case"textarea":r.autoFocus&&l.focus();break e;case"img":r.src?l.src=r.src:r.srcSet&&(l.srcset=r.srcSet)}}catch(f){it(e,e.return,f)}}function L0(e,n,r){try{var l=e.stateNode;d4(l,e.type,r,n),l[be]=n}catch(f){it(e,e.return,f)}}function bm(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&hr(e.type)||e.tag===4}function j0(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||bm(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&hr(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function F0(e,n,r){var l=e.tag;if(l===5||l===6)e=e.stateNode,n?(r.nodeType===9?r.body:r.nodeName==="HTML"?r.ownerDocument.body:r).insertBefore(e,n):(n=r.nodeType===9?r.body:r.nodeName==="HTML"?r.ownerDocument.body:r,n.appendChild(e),r=r._reactRootContainer,r!=null||n.onclick!==null||(n.onclick=Sa));else if(l!==4&&(l===27&&hr(e.type)&&(r=e.stateNode,n=null),e=e.child,e!==null))for(F0(e,n,r),e=e.sibling;e!==null;)F0(e,n,r),e=e.sibling}function xs(e,n,r){var l=e.tag;if(l===5||l===6)e=e.stateNode,n?r.insertBefore(e,n):r.appendChild(e);else if(l!==4&&(l===27&&hr(e.type)&&(r=e.stateNode),e=e.child,e!==null))for(xs(e,n,r),e=e.sibling;e!==null;)xs(e,n,r),e=e.sibling}function Em(e){var n=e.stateNode,r=e.memoizedProps;try{for(var l=e.type,f=n.attributes;f.length;)n.removeAttributeNode(f[0]);Jt(n,l,r),n[Ce]=e,n[be]=r}catch(h){it(e,e.return,h)}}var La=!1,$t=!1,k0=!1,Sm=typeof WeakSet=="function"?WeakSet:Set,Yt=null;function q9(e,n){if(e=e.containerInfo,a2=qs,e=Fh(e),Mc(e)){if("selectionStart"in e)var r={start:e.selectionStart,end:e.selectionEnd};else e:{r=(r=e.ownerDocument)&&r.defaultView||window;var l=r.getSelection&&r.getSelection();if(l&&l.rangeCount!==0){r=l.anchorNode;var f=l.anchorOffset,h=l.focusNode;l=l.focusOffset;try{r.nodeType,h.nodeType}catch{r=null;break e}var E=0,M=-1,k=-1,Q=0,ae=0,le=e,Z=null;t:for(;;){for(var ee;le!==r||f!==0&&le.nodeType!==3||(M=E+f),le!==h||l!==0&&le.nodeType!==3||(k=E+l),le.nodeType===3&&(E+=le.nodeValue.length),(ee=le.firstChild)!==null;)Z=le,le=ee;for(;;){if(le===e)break t;if(Z===r&&++Q===f&&(M=E),Z===h&&++ae===l&&(k=E),(ee=le.nextSibling)!==null)break;le=Z,Z=le.parentNode}le=ee}r=M===-1||k===-1?null:{start:M,end:k}}else r=null}r=r||{start:0,end:0}}else r=null;for(r2={focusedElem:e,selectionRange:r},qs=!1,Yt=n;Yt!==null;)if(n=Yt,e=n.child,(n.subtreeFlags&1028)!==0&&e!==null)e.return=n,Yt=e;else for(;Yt!==null;){switch(n=Yt,h=n.alternate,e=n.flags,n.tag){case 0:if((e&4)!==0&&(e=n.updateQueue,e=e!==null?e.events:null,e!==null))for(r=0;r<e.length;r++)f=e[r],f.ref.impl=f.nextImpl;break;case 11:case 15:break;case 1:if((e&1024)!==0&&h!==null){e=void 0,r=n,f=h.memoizedProps,h=h.memoizedState,l=r.stateNode;try{var xe=qr(r.type,f);e=l.getSnapshotBeforeUpdate(xe,h),l.__reactInternalSnapshotBeforeUpdate=e}catch(Le){it(r,r.return,Le)}}break;case 3:if((e&1024)!==0){if(e=n.stateNode.containerInfo,r=e.nodeType,r===9)l2(e);else if(r===1)switch(e.nodeName){case"HEAD":case"HTML":case"BODY":l2(e);break;default:e.textContent=""}}break;case 5:case 26:case 27:case 6:case 4:case 17:break;default:if((e&1024)!==0)throw Error(i(163))}if(e=n.sibling,e!==null){e.return=n.return,Yt=e;break}Yt=n.return}}function xm(e,n,r){var l=r.flags;switch(r.tag){case 0:case 11:case 15:Fa(e,r),l&4&&Ii(5,r);break;case 1:if(Fa(e,r),l&4)if(e=r.stateNode,n===null)try{e.componentDidMount()}catch(E){it(r,r.return,E)}else{var f=qr(r.type,n.memoizedProps);n=n.memoizedState;try{e.componentDidUpdate(f,n,e.__reactInternalSnapshotBeforeUpdate)}catch(E){it(r,r.return,E)}}l&64&&ym(r),l&512&&Hi(r,r.return);break;case 3:if(Fa(e,r),l&64&&(e=r.updateQueue,e!==null)){if(n=null,r.child!==null)switch(r.child.tag){case 27:case 5:n=r.child.stateNode;break;case 1:n=r.child.stateNode}try{sp(e,n)}catch(E){it(r,r.return,E)}}break;case 27:n===null&&l&4&&Em(r);case 26:case 5:Fa(e,r),n===null&&l&4&&Cm(r),l&512&&Hi(r,r.return);break;case 12:Fa(e,r);break;case 31:Fa(e,r),l&4&&Rm(e,r);break;case 13:Fa(e,r),l&4&&Tm(e,r),l&64&&(e=r.memoizedState,e!==null&&(e=e.dehydrated,e!==null&&(r=e4.bind(null,r),C4(e,r))));break;case 22:if(l=r.memoizedState!==null||La,!l){n=n!==null&&n.memoizedState!==null||$t,f=La;var h=$t;La=l,($t=n)&&!h?ka(e,r,(r.subtreeFlags&8772)!==0):Fa(e,r),La=f,$t=h}break;case 30:break;default:Fa(e,r)}}function wm(e){var n=e.alternate;n!==null&&(e.alternate=null,wm(n)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(n=e.stateNode,n!==null&&dt(n)),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}var wt=null,dn=!1;function ja(e,n,r){for(r=r.child;r!==null;)_m(e,n,r),r=r.sibling}function _m(e,n,r){if(mt&&typeof mt.onCommitFiberUnmount=="function")try{mt.onCommitFiberUnmount(zt,r)}catch{}switch(r.tag){case 26:$t||ha(r,n),ja(e,n,r),r.memoizedState?r.memoizedState.count--:r.stateNode&&(r=r.stateNode,r.parentNode.removeChild(r));break;case 27:$t||ha(r,n);var l=wt,f=dn;hr(r.type)&&(wt=r.stateNode,dn=!1),ja(e,n,r),Xi(r.stateNode),wt=l,dn=f;break;case 5:$t||ha(r,n);case 6:if(l=wt,f=dn,wt=null,ja(e,n,r),wt=l,dn=f,wt!==null)if(dn)try{(wt.nodeType===9?wt.body:wt.nodeName==="HTML"?wt.ownerDocument.body:wt).removeChild(r.stateNode)}catch(h){it(r,n,h)}else try{wt.removeChild(r.stateNode)}catch(h){it(r,n,h)}break;case 18:wt!==null&&(dn?(e=wt,yv(e.nodeType===9?e.body:e.nodeName==="HTML"?e.ownerDocument.body:e,r.stateNode),Vo(e)):yv(wt,r.stateNode));break;case 4:l=wt,f=dn,wt=r.stateNode.containerInfo,dn=!0,ja(e,n,r),wt=l,dn=f;break;case 0:case 11:case 14:case 15:ir(2,r,n),$t||ir(4,r,n),ja(e,n,r);break;case 1:$t||(ha(r,n),l=r.stateNode,typeof l.componentWillUnmount=="function"&&Am(r,n,l)),ja(e,n,r);break;case 21:ja(e,n,r);break;case 22:$t=(l=$t)||r.memoizedState!==null,ja(e,n,r),$t=l;break;default:ja(e,n,r)}}function Rm(e,n){if(n.memoizedState===null&&(e=n.alternate,e!==null&&(e=e.memoizedState,e!==null))){e=e.dehydrated;try{Vo(e)}catch(r){it(n,n.return,r)}}}function Tm(e,n){if(n.memoizedState===null&&(e=n.alternate,e!==null&&(e=e.memoizedState,e!==null&&(e=e.dehydrated,e!==null))))try{Vo(e)}catch(r){it(n,n.return,r)}}function G9(e){switch(e.tag){case 31:case 13:case 19:var n=e.stateNode;return n===null&&(n=e.stateNode=new Sm),n;case 22:return e=e.stateNode,n=e._retryCache,n===null&&(n=e._retryCache=new Sm),n;default:throw Error(i(435,e.tag))}}function ws(e,n){var r=G9(e);n.forEach(function(l){if(!r.has(l)){r.add(l);var f=t4.bind(null,e,l);l.then(f,f)}})}function hn(e,n){var r=n.deletions;if(r!==null)for(var l=0;l<r.length;l++){var f=r[l],h=e,E=n,M=E;e:for(;M!==null;){switch(M.tag){case 27:if(hr(M.type)){wt=M.stateNode,dn=!1;break e}break;case 5:wt=M.stateNode,dn=!1;break e;case 3:case 4:wt=M.stateNode.containerInfo,dn=!0;break e}M=M.return}if(wt===null)throw Error(i(160));_m(h,E,f),wt=null,dn=!1,h=f.alternate,h!==null&&(h.return=null),f.return=null}if(n.subtreeFlags&13886)for(n=n.child;n!==null;)Mm(n,e),n=n.sibling}var Wn=null;function Mm(e,n){var r=e.alternate,l=e.flags;switch(e.tag){case 0:case 11:case 14:case 15:hn(n,e),pn(e),l&4&&(ir(3,e,e.return),Ii(3,e),ir(5,e,e.return));break;case 1:hn(n,e),pn(e),l&512&&($t||r===null||ha(r,r.return)),l&64&&La&&(e=e.updateQueue,e!==null&&(l=e.callbacks,l!==null&&(r=e.shared.hiddenCallbacks,e.shared.hiddenCallbacks=r===null?l:r.concat(l))));break;case 26:var f=Wn;if(hn(n,e),pn(e),l&512&&($t||r===null||ha(r,r.return)),l&4){var h=r!==null?r.memoizedState:null;if(l=e.memoizedState,r===null)if(l===null)if(e.stateNode===null){e:{l=e.type,r=e.memoizedProps,f=f.ownerDocument||f;t:switch(l){case"title":h=f.getElementsByTagName("title")[0],(!h||h[Be]||h[Ce]||h.namespaceURI==="http://www.w3.org/2000/svg"||h.hasAttribute("itemprop"))&&(h=f.createElement(l),f.head.insertBefore(h,f.querySelector("head > title"))),Jt(h,l,r),h[Ce]=e,vt(h),l=h;break e;case"link":var E=Mv("link","href",f).get(l+(r.href||""));if(E){for(var M=0;M<E.length;M++)if(h=E[M],h.getAttribute("href")===(r.href==null||r.href===""?null:r.href)&&h.getAttribute("rel")===(r.rel==null?null:r.rel)&&h.getAttribute("title")===(r.title==null?null:r.title)&&h.getAttribute("crossorigin")===(r.crossOrigin==null?null:r.crossOrigin)){E.splice(M,1);break t}}h=f.createElement(l),Jt(h,l,r),f.head.appendChild(h);break;case"meta":if(E=Mv("meta","content",f).get(l+(r.content||""))){for(M=0;M<E.length;M++)if(h=E[M],h.getAttribute("content")===(r.content==null?null:""+r.content)&&h.getAttribute("name")===(r.name==null?null:r.name)&&h.getAttribute("property")===(r.property==null?null:r.property)&&h.getAttribute("http-equiv")===(r.httpEquiv==null?null:r.httpEquiv)&&h.getAttribute("charset")===(r.charSet==null?null:r.charSet)){E.splice(M,1);break t}}h=f.createElement(l),Jt(h,l,r),f.head.appendChild(h);break;default:throw Error(i(468,l))}h[Ce]=e,vt(h),l=h}e.stateNode=l}else Dv(f,e.type,e.stateNode);else e.stateNode=Tv(f,l,e.memoizedProps);else h!==l?(h===null?r.stateNode!==null&&(r=r.stateNode,r.parentNode.removeChild(r)):h.count--,l===null?Dv(f,e.type,e.stateNode):Tv(f,l,e.memoizedProps)):l===null&&e.stateNode!==null&&L0(e,e.memoizedProps,r.memoizedProps)}break;case 27:hn(n,e),pn(e),l&512&&($t||r===null||ha(r,r.return)),r!==null&&l&4&&L0(e,e.memoizedProps,r.memoizedProps);break;case 5:if(hn(n,e),pn(e),l&512&&($t||r===null||ha(r,r.return)),e.flags&32){f=e.stateNode;try{ho(f,"")}catch(xe){it(e,e.return,xe)}}l&4&&e.stateNode!=null&&(f=e.memoizedProps,L0(e,f,r!==null?r.memoizedProps:f)),l&1024&&(k0=!0);break;case 6:if(hn(n,e),pn(e),l&4){if(e.stateNode===null)throw Error(i(162));l=e.memoizedProps,r=e.stateNode;try{r.nodeValue=l}catch(xe){it(e,e.return,xe)}}break;case 3:if(Hs=null,f=Wn,Wn=Ps(n.containerInfo),hn(n,e),Wn=f,pn(e),l&4&&r!==null&&r.memoizedState.isDehydrated)try{Vo(n.containerInfo)}catch(xe){it(e,e.return,xe)}k0&&(k0=!1,Dm(e));break;case 4:l=Wn,Wn=Ps(e.stateNode.containerInfo),hn(n,e),pn(e),Wn=l;break;case 12:hn(n,e),pn(e);break;case 31:hn(n,e),pn(e),l&4&&(l=e.updateQueue,l!==null&&(e.updateQueue=null,ws(e,l)));break;case 13:hn(n,e),pn(e),e.child.flags&8192&&e.memoizedState!==null!=(r!==null&&r.memoizedState!==null)&&(Rs=kt()),l&4&&(l=e.updateQueue,l!==null&&(e.updateQueue=null,ws(e,l)));break;case 22:f=e.memoizedState!==null;var k=r!==null&&r.memoizedState!==null,Q=La,ae=$t;if(La=Q||f,$t=ae||k,hn(n,e),$t=ae,La=Q,pn(e),l&8192)e:for(n=e.stateNode,n._visibility=f?n._visibility&-2:n._visibility|1,f&&(r===null||k||La||$t||Gr(e)),r=null,n=e;;){if(n.tag===5||n.tag===26){if(r===null){k=r=n;try{if(h=k.stateNode,f)E=h.style,typeof E.setProperty=="function"?E.setProperty("display","none","important"):E.display="none";else{M=k.stateNode;var le=k.memoizedProps.style,Z=le!=null&&le.hasOwnProperty("display")?le.display:null;M.style.display=Z==null||typeof Z=="boolean"?"":(""+Z).trim()}}catch(xe){it(k,k.return,xe)}}}else if(n.tag===6){if(r===null){k=n;try{k.stateNode.nodeValue=f?"":k.memoizedProps}catch(xe){it(k,k.return,xe)}}}else if(n.tag===18){if(r===null){k=n;try{var ee=k.stateNode;f?Av(ee,!0):Av(k.stateNode,!1)}catch(xe){it(k,k.return,xe)}}}else if((n.tag!==22&&n.tag!==23||n.memoizedState===null||n===e)&&n.child!==null){n.child.return=n,n=n.child;continue}if(n===e)break e;for(;n.sibling===null;){if(n.return===null||n.return===e)break e;r===n&&(r=null),n=n.return}r===n&&(r=null),n.sibling.return=n.return,n=n.sibling}l&4&&(l=e.updateQueue,l!==null&&(r=l.retryQueue,r!==null&&(l.retryQueue=null,ws(e,r))));break;case 19:hn(n,e),pn(e),l&4&&(l=e.updateQueue,l!==null&&(e.updateQueue=null,ws(e,l)));break;case 30:break;case 21:break;default:hn(n,e),pn(e)}}function pn(e){var n=e.flags;if(n&2){try{for(var r,l=e.return;l!==null;){if(bm(l)){r=l;break}l=l.return}if(r==null)throw Error(i(160));switch(r.tag){case 27:var f=r.stateNode,h=j0(e);xs(e,h,f);break;case 5:var E=r.stateNode;r.flags&32&&(ho(E,""),r.flags&=-33);var M=j0(e);xs(e,M,E);break;case 3:case 4:var k=r.stateNode.containerInfo,Q=j0(e);F0(e,Q,k);break;default:throw Error(i(161))}}catch(ae){it(e,e.return,ae)}e.flags&=-3}n&4096&&(e.flags&=-4097)}function Dm(e){if(e.subtreeFlags&1024)for(e=e.child;e!==null;){var n=e;Dm(n),n.tag===5&&n.flags&1024&&n.stateNode.reset(),e=e.sibling}}function Fa(e,n){if(n.subtreeFlags&8772)for(n=n.child;n!==null;)xm(e,n.alternate,n),n=n.sibling}function Gr(e){for(e=e.child;e!==null;){var n=e;switch(n.tag){case 0:case 11:case 14:case 15:ir(4,n,n.return),Gr(n);break;case 1:ha(n,n.return);var r=n.stateNode;typeof r.componentWillUnmount=="function"&&Am(n,n.return,r),Gr(n);break;case 27:Xi(n.stateNode);case 26:case 5:ha(n,n.return),Gr(n);break;case 22:n.memoizedState===null&&Gr(n);break;case 30:Gr(n);break;default:Gr(n)}e=e.sibling}}function ka(e,n,r){for(r=r&&(n.subtreeFlags&8772)!==0,n=n.child;n!==null;){var l=n.alternate,f=e,h=n,E=h.flags;switch(h.tag){case 0:case 11:case 15:ka(f,h,r),Ii(4,h);break;case 1:if(ka(f,h,r),l=h,f=l.stateNode,typeof f.componentDidMount=="function")try{f.componentDidMount()}catch(Q){it(l,l.return,Q)}if(l=h,f=l.updateQueue,f!==null){var M=l.stateNode;try{var k=f.shared.hiddenCallbacks;if(k!==null)for(f.shared.hiddenCallbacks=null,f=0;f<k.length;f++)lp(k[f],M)}catch(Q){it(l,l.return,Q)}}r&&E&64&&ym(h),Hi(h,h.return);break;case 27:Em(h);case 26:case 5:ka(f,h,r),r&&l===null&&E&4&&Cm(h),Hi(h,h.return);break;case 12:ka(f,h,r);break;case 31:ka(f,h,r),r&&E&4&&Rm(f,h);break;case 13:ka(f,h,r),r&&E&4&&Tm(f,h);break;case 22:h.memoizedState===null&&ka(f,h,r),Hi(h,h.return);break;case 30:break;default:ka(f,h,r)}n=n.sibling}}function z0(e,n){var r=null;e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(r=e.memoizedState.cachePool.pool),e=null,n.memoizedState!==null&&n.memoizedState.cachePool!==null&&(e=n.memoizedState.cachePool.pool),e!==r&&(e!=null&&e.refCount++,r!=null&&Ri(r))}function U0(e,n){e=null,n.alternate!==null&&(e=n.alternate.memoizedState.cache),n=n.memoizedState.cache,n!==e&&(n.refCount++,e!=null&&Ri(e))}function ea(e,n,r,l){if(n.subtreeFlags&10256)for(n=n.child;n!==null;)Om(e,n,r,l),n=n.sibling}function Om(e,n,r,l){var f=n.flags;switch(n.tag){case 0:case 11:case 15:ea(e,n,r,l),f&2048&&Ii(9,n);break;case 1:ea(e,n,r,l);break;case 3:ea(e,n,r,l),f&2048&&(e=null,n.alternate!==null&&(e=n.alternate.memoizedState.cache),n=n.memoizedState.cache,n!==e&&(n.refCount++,e!=null&&Ri(e)));break;case 12:if(f&2048){ea(e,n,r,l),e=n.stateNode;try{var h=n.memoizedProps,E=h.id,M=h.onPostCommit;typeof M=="function"&&M(E,n.alternate===null?"mount":"update",e.passiveEffectDuration,-0)}catch(k){it(n,n.return,k)}}else ea(e,n,r,l);break;case 31:ea(e,n,r,l);break;case 13:ea(e,n,r,l);break;case 23:break;case 22:h=n.stateNode,E=n.alternate,n.memoizedState!==null?h._visibility&2?ea(e,n,r,l):Bi(e,n):h._visibility&2?ea(e,n,r,l):(h._visibility|=2,Lo(e,n,r,l,(n.subtreeFlags&10256)!==0||!1)),f&2048&&z0(E,n);break;case 24:ea(e,n,r,l),f&2048&&U0(n.alternate,n);break;default:ea(e,n,r,l)}}function Lo(e,n,r,l,f){for(f=f&&((n.subtreeFlags&10256)!==0||!1),n=n.child;n!==null;){var h=e,E=n,M=r,k=l,Q=E.flags;switch(E.tag){case 0:case 11:case 15:Lo(h,E,M,k,f),Ii(8,E);break;case 23:break;case 22:var ae=E.stateNode;E.memoizedState!==null?ae._visibility&2?Lo(h,E,M,k,f):Bi(h,E):(ae._visibility|=2,Lo(h,E,M,k,f)),f&&Q&2048&&z0(E.alternate,E);break;case 24:Lo(h,E,M,k,f),f&&Q&2048&&U0(E.alternate,E);break;default:Lo(h,E,M,k,f)}n=n.sibling}}function Bi(e,n){if(n.subtreeFlags&10256)for(n=n.child;n!==null;){var r=e,l=n,f=l.flags;switch(l.tag){case 22:Bi(r,l),f&2048&&z0(l.alternate,l);break;case 24:Bi(r,l),f&2048&&U0(l.alternate,l);break;default:Bi(r,l)}n=n.sibling}}var $i=8192;function jo(e,n,r){if(e.subtreeFlags&$i)for(e=e.child;e!==null;)Nm(e,n,r),e=e.sibling}function Nm(e,n,r){switch(e.tag){case 26:jo(e,n,r),e.flags&$i&&e.memoizedState!==null&&N4(r,Wn,e.memoizedState,e.memoizedProps);break;case 5:jo(e,n,r);break;case 3:case 4:var l=Wn;Wn=Ps(e.stateNode.containerInfo),jo(e,n,r),Wn=l;break;case 22:e.memoizedState===null&&(l=e.alternate,l!==null&&l.memoizedState!==null?(l=$i,$i=16777216,jo(e,n,r),$i=l):jo(e,n,r));break;default:jo(e,n,r)}}function Lm(e){var n=e.alternate;if(n!==null&&(e=n.child,e!==null)){n.child=null;do n=e.sibling,e.sibling=null,e=n;while(e!==null)}}function Vi(e){var n=e.deletions;if((e.flags&16)!==0){if(n!==null)for(var r=0;r<n.length;r++){var l=n[r];Yt=l,Fm(l,e)}Lm(e)}if(e.subtreeFlags&10256)for(e=e.child;e!==null;)jm(e),e=e.sibling}function jm(e){switch(e.tag){case 0:case 11:case 15:Vi(e),e.flags&2048&&ir(9,e,e.return);break;case 3:Vi(e);break;case 12:Vi(e);break;case 22:var n=e.stateNode;e.memoizedState!==null&&n._visibility&2&&(e.return===null||e.return.tag!==13)?(n._visibility&=-3,_s(e)):Vi(e);break;default:Vi(e)}}function _s(e){var n=e.deletions;if((e.flags&16)!==0){if(n!==null)for(var r=0;r<n.length;r++){var l=n[r];Yt=l,Fm(l,e)}Lm(e)}for(e=e.child;e!==null;){switch(n=e,n.tag){case 0:case 11:case 15:ir(8,n,n.return),_s(n);break;case 22:r=n.stateNode,r._visibility&2&&(r._visibility&=-3,_s(n));break;default:_s(n)}e=e.sibling}}function Fm(e,n){for(;Yt!==null;){var r=Yt;switch(r.tag){case 0:case 11:case 15:ir(8,r,n);break;case 23:case 22:if(r.memoizedState!==null&&r.memoizedState.cachePool!==null){var l=r.memoizedState.cachePool.pool;l!=null&&l.refCount++}break;case 24:Ri(r.memoizedState.cache)}if(l=r.child,l!==null)l.return=r,Yt=l;else e:for(r=e;Yt!==null;){l=Yt;var f=l.sibling,h=l.return;if(wm(l),l===r){Yt=null;break e}if(f!==null){f.return=h,Yt=f;break e}Yt=h}}}var Y9={getCacheForType:function(e){var n=Xt(It),r=n.data.get(e);return r===void 0&&(r=e(),n.data.set(e,r)),r},cacheSignal:function(){return Xt(It).controller.signal}},Q9=typeof WeakMap=="function"?WeakMap:Map,nt=0,ht=null,Ve=null,Ge=0,ot=0,Sn=null,lr=!1,Fo=!1,P0=!1,za=0,Mt=0,sr=0,Yr=0,I0=0,xn=0,ko=0,qi=null,mn=null,H0=!1,Rs=0,km=0,Ts=1/0,Ms=null,ur=null,Vt=0,cr=null,zo=null,Ua=0,B0=0,$0=null,zm=null,Gi=0,V0=null;function wn(){return(nt&2)!==0&&Ge!==0?Ge&-Ge:U.T!==null?X0():he()}function Um(){if(xn===0)if((Ge&536870912)===0||Qe){var e=Ea;Ea<<=1,(Ea&3932160)===0&&(Ea=262144),xn=e}else xn=536870912;return e=bn.current,e!==null&&(e.flags|=32),xn}function vn(e,n,r){(e===ht&&(ot===2||ot===9)||e.cancelPendingCommit!==null)&&(Uo(e,0),fr(e,Ge,xn,!1)),sa(e,r),((nt&2)===0||e!==ht)&&(e===ht&&((nt&2)===0&&(Yr|=r),Mt===4&&fr(e,Ge,xn,!1)),pa(e))}function Pm(e,n,r){if((nt&6)!==0)throw Error(i(327));var l=!r&&(n&127)===0&&(n&e.expiredLanes)===0||Ya(e,n),f=l?Z9(e,n):G0(e,n,!0),h=l;do{if(f===0){Fo&&!l&&fr(e,n,0,!1);break}else{if(r=e.current.alternate,h&&!K9(r)){f=G0(e,n,!1),h=!1;continue}if(f===2){if(h=n,e.errorRecoveryDisabledLanes&h)var E=0;else E=e.pendingLanes&-536870913,E=E!==0?E:E&536870912?536870912:0;if(E!==0){n=E;e:{var M=e;f=qi;var k=M.current.memoizedState.isDehydrated;if(k&&(Uo(M,E).flags|=256),E=G0(M,E,!1),E!==2){if(P0&&!k){M.errorRecoveryDisabledLanes|=h,Yr|=h,f=4;break e}h=mn,mn=f,h!==null&&(mn===null?mn=h:mn.push.apply(mn,h))}f=E}if(h=!1,f!==2)continue}}if(f===1){Uo(e,0),fr(e,n,0,!0);break}e:{switch(l=e,h=f,h){case 0:case 1:throw Error(i(345));case 4:if((n&4194048)!==n)break;case 6:fr(l,n,xn,!lr);break e;case 2:mn=null;break;case 3:case 5:break;default:throw Error(i(329))}if((n&62914560)===n&&(f=Rs+300-kt(),10<f)){if(fr(l,n,xn,!lr),lo(l,0,!0)!==0)break e;Ua=n,l.timeoutHandle=vv(Im.bind(null,l,r,mn,Ms,H0,n,xn,Yr,ko,lr,h,"Throttled",-0,0),f);break e}Im(l,r,mn,Ms,H0,n,xn,Yr,ko,lr,h,null,-0,0)}}break}while(!0);pa(e)}function Im(e,n,r,l,f,h,E,M,k,Q,ae,le,Z,ee){if(e.timeoutHandle=-1,le=n.subtreeFlags,le&8192||(le&16785408)===16785408){le={stylesheets:null,count:0,imgCount:0,imgBytes:0,suspenseyImages:[],waitingForImages:!0,waitingForViewTransition:!1,unsuspend:Sa},Nm(n,h,le);var xe=(h&62914560)===h?Rs-kt():(h&4194048)===h?km-kt():0;if(xe=L4(le,xe),xe!==null){Ua=h,e.cancelPendingCommit=xe(Qm.bind(null,e,n,h,r,l,f,E,M,k,ae,le,null,Z,ee)),fr(e,h,E,!Q);return}}Qm(e,n,h,r,l,f,E,M,k)}function K9(e){for(var n=e;;){var r=n.tag;if((r===0||r===11||r===15)&&n.flags&16384&&(r=n.updateQueue,r!==null&&(r=r.stores,r!==null)))for(var l=0;l<r.length;l++){var f=r[l],h=f.getSnapshot;f=f.value;try{if(!An(h(),f))return!1}catch{return!1}}if(r=n.child,n.subtreeFlags&16384&&r!==null)r.return=n,n=r;else{if(n===e)break;for(;n.sibling===null;){if(n.return===null||n.return===e)return!0;n=n.return}n.sibling.return=n.return,n=n.sibling}}return!0}function fr(e,n,r,l){n&=~I0,n&=~Yr,e.suspendedLanes|=n,e.pingedLanes&=~n,l&&(e.warmLanes|=n),l=e.expirationTimes;for(var f=n;0<f;){var h=31-tn(f),E=1<<h;l[h]=-1,f&=~E}r!==0&&Pl(e,r,n)}function Ds(){return(nt&6)===0?(Yi(0),!1):!0}function q0(){if(Ve!==null){if(ot===0)var e=Ve.return;else e=Ve,Ra=Ur=null,l0(e),To=null,Mi=0,e=Ve;for(;e!==null;)gm(e.alternate,e),e=e.return;Ve=null}}function Uo(e,n){var r=e.timeoutHandle;r!==-1&&(e.timeoutHandle=-1,m4(r)),r=e.cancelPendingCommit,r!==null&&(e.cancelPendingCommit=null,r()),Ua=0,q0(),ht=e,Ve=r=wa(e.current,null),Ge=n,ot=0,Sn=null,lr=!1,Fo=Ya(e,n),P0=!1,ko=xn=I0=Yr=sr=Mt=0,mn=qi=null,H0=!1,(n&8)!==0&&(n|=n&32);var l=e.entangledLanes;if(l!==0)for(e=e.entanglements,l&=n;0<l;){var f=31-tn(l),h=1<<f;n|=e[f],l&=~h}return za=n,Zl(),r}function Hm(e,n){ze=null,U.H=zi,n===Ro||n===os?(n=ap(),ot=3):n===Kc?(n=ap(),ot=4):ot=n===S0?8:n!==null&&typeof n=="object"&&typeof n.then=="function"?6:1,Sn=n,Ve===null&&(Mt=1,As(e,Fn(n,e.current)))}function Bm(){var e=bn.current;return e===null?!0:(Ge&4194048)===Ge?Pn===null:(Ge&62914560)===Ge||(Ge&536870912)!==0?e===Pn:!1}function $m(){var e=U.H;return U.H=zi,e===null?zi:e}function Vm(){var e=U.A;return U.A=Y9,e}function Os(){Mt=4,lr||(Ge&4194048)!==Ge&&bn.current!==null||(Fo=!0),(sr&134217727)===0&&(Yr&134217727)===0||ht===null||fr(ht,Ge,xn,!1)}function G0(e,n,r){var l=nt;nt|=2;var f=$m(),h=Vm();(ht!==e||Ge!==n)&&(Ms=null,Uo(e,n)),n=!1;var E=Mt;e:do try{if(ot!==0&&Ve!==null){var M=Ve,k=Sn;switch(ot){case 8:q0(),E=6;break e;case 3:case 2:case 9:case 6:bn.current===null&&(n=!0);var Q=ot;if(ot=0,Sn=null,Po(e,M,k,Q),r&&Fo){E=0;break e}break;default:Q=ot,ot=0,Sn=null,Po(e,M,k,Q)}}X9(),E=Mt;break}catch(ae){Hm(e,ae)}while(!0);return n&&e.shellSuspendCounter++,Ra=Ur=null,nt=l,U.H=f,U.A=h,Ve===null&&(ht=null,Ge=0,Zl()),E}function X9(){for(;Ve!==null;)qm(Ve)}function Z9(e,n){var r=nt;nt|=2;var l=$m(),f=Vm();ht!==e||Ge!==n?(Ms=null,Ts=kt()+500,Uo(e,n)):Fo=Ya(e,n);e:do try{if(ot!==0&&Ve!==null){n=Ve;var h=Sn;t:switch(ot){case 1:ot=0,Sn=null,Po(e,n,h,1);break;case 2:case 9:if(tp(h)){ot=0,Sn=null,Gm(n);break}n=function(){ot!==2&&ot!==9||ht!==e||(ot=7),pa(e)},h.then(n,n);break e;case 3:ot=7;break e;case 4:ot=5;break e;case 7:tp(h)?(ot=0,Sn=null,Gm(n)):(ot=0,Sn=null,Po(e,n,h,7));break;case 5:var E=null;switch(Ve.tag){case 26:E=Ve.memoizedState;case 5:case 27:var M=Ve;if(E?Ov(E):M.stateNode.complete){ot=0,Sn=null;var k=M.sibling;if(k!==null)Ve=k;else{var Q=M.return;Q!==null?(Ve=Q,Ns(Q)):Ve=null}break t}}ot=0,Sn=null,Po(e,n,h,5);break;case 6:ot=0,Sn=null,Po(e,n,h,6);break;case 8:q0(),Mt=6;break e;default:throw Error(i(462))}}J9();break}catch(ae){Hm(e,ae)}while(!0);return Ra=Ur=null,U.H=l,U.A=f,nt=r,Ve!==null?0:(ht=null,Ge=0,Zl(),Mt)}function J9(){for(;Ve!==null&&!Nn();)qm(Ve)}function qm(e){var n=mm(e.alternate,e,za);e.memoizedProps=e.pendingProps,n===null?Ns(e):Ve=n}function Gm(e){var n=e,r=n.alternate;switch(n.tag){case 15:case 0:n=um(r,n,n.pendingProps,n.type,void 0,Ge);break;case 11:n=um(r,n,n.pendingProps,n.type.render,n.ref,Ge);break;case 5:l0(n);default:gm(r,n),n=Ve=Vh(n,za),n=mm(r,n,za)}e.memoizedProps=e.pendingProps,n===null?Ns(e):Ve=n}function Po(e,n,r,l){Ra=Ur=null,l0(n),To=null,Mi=0;var f=n.return;try{if(I9(e,f,n,r,Ge)){Mt=1,As(e,Fn(r,e.current)),Ve=null;return}}catch(h){if(f!==null)throw Ve=f,h;Mt=1,As(e,Fn(r,e.current)),Ve=null;return}n.flags&32768?(Qe||l===1?e=!0:Fo||(Ge&536870912)!==0?e=!1:(lr=e=!0,(l===2||l===9||l===3||l===6)&&(l=bn.current,l!==null&&l.tag===13&&(l.flags|=16384))),Ym(n,e)):Ns(n)}function Ns(e){var n=e;do{if((n.flags&32768)!==0){Ym(n,lr);return}e=n.return;var r=$9(n.alternate,n,za);if(r!==null){Ve=r;return}if(n=n.sibling,n!==null){Ve=n;return}Ve=n=e}while(n!==null);Mt===0&&(Mt=5)}function Ym(e,n){do{var r=V9(e.alternate,e);if(r!==null){r.flags&=32767,Ve=r;return}if(r=e.return,r!==null&&(r.flags|=32768,r.subtreeFlags=0,r.deletions=null),!n&&(e=e.sibling,e!==null)){Ve=e;return}Ve=e=r}while(e!==null);Mt=6,Ve=null}function Qm(e,n,r,l,f,h,E,M,k){e.cancelPendingCommit=null;do Ls();while(Vt!==0);if((nt&6)!==0)throw Error(i(327));if(n!==null){if(n===e.current)throw Error(i(177));if(h=n.lanes|n.childLanes,h|=jc,Ul(e,r,h,E,M,k),e===ht&&(Ve=ht=null,Ge=0),zo=n,cr=e,Ua=r,B0=h,$0=f,zm=l,(n.subtreeFlags&10256)!==0||(n.flags&10256)!==0?(e.callbackNode=null,e.callbackPriority=0,n4(ve,function(){return Wm(),null})):(e.callbackNode=null,e.callbackPriority=0),l=(n.flags&13878)!==0,(n.subtreeFlags&13878)!==0||l){l=U.T,U.T=null,f=H.p,H.p=2,E=nt,nt|=4;try{q9(e,n,r)}finally{nt=E,H.p=f,U.T=l}}Vt=1,Km(),Xm(),Zm()}}function Km(){if(Vt===1){Vt=0;var e=cr,n=zo,r=(n.flags&13878)!==0;if((n.subtreeFlags&13878)!==0||r){r=U.T,U.T=null;var l=H.p;H.p=2;var f=nt;nt|=4;try{Mm(n,e);var h=r2,E=Fh(e.containerInfo),M=h.focusedElem,k=h.selectionRange;if(E!==M&&M&&M.ownerDocument&&jh(M.ownerDocument.documentElement,M)){if(k!==null&&Mc(M)){var Q=k.start,ae=k.end;if(ae===void 0&&(ae=Q),"selectionStart"in M)M.selectionStart=Q,M.selectionEnd=Math.min(ae,M.value.length);else{var le=M.ownerDocument||document,Z=le&&le.defaultView||window;if(Z.getSelection){var ee=Z.getSelection(),xe=M.textContent.length,Le=Math.min(k.start,xe),ct=k.end===void 0?Le:Math.min(k.end,xe);!ee.extend&&Le>ct&&(E=ct,ct=Le,Le=E);var V=Lh(M,Le),P=Lh(M,ct);if(V&&P&&(ee.rangeCount!==1||ee.anchorNode!==V.node||ee.anchorOffset!==V.offset||ee.focusNode!==P.node||ee.focusOffset!==P.offset)){var Y=le.createRange();Y.setStart(V.node,V.offset),ee.removeAllRanges(),Le>ct?(ee.addRange(Y),ee.extend(P.node,P.offset)):(Y.setEnd(P.node,P.offset),ee.addRange(Y))}}}}for(le=[],ee=M;ee=ee.parentNode;)ee.nodeType===1&&le.push({element:ee,left:ee.scrollLeft,top:ee.scrollTop});for(typeof M.focus=="function"&&M.focus(),M=0;M<le.length;M++){var oe=le[M];oe.element.scrollLeft=oe.left,oe.element.scrollTop=oe.top}}qs=!!a2,r2=a2=null}finally{nt=f,H.p=l,U.T=r}}e.current=n,Vt=2}}function Xm(){if(Vt===2){Vt=0;var e=cr,n=zo,r=(n.flags&8772)!==0;if((n.subtreeFlags&8772)!==0||r){r=U.T,U.T=null;var l=H.p;H.p=2;var f=nt;nt|=4;try{xm(e,n.alternate,n)}finally{nt=f,H.p=l,U.T=r}}Vt=3}}function Zm(){if(Vt===4||Vt===3){Vt=0,Ue();var e=cr,n=zo,r=Ua,l=zm;(n.subtreeFlags&10256)!==0||(n.flags&10256)!==0?Vt=5:(Vt=0,zo=cr=null,Jm(e,e.pendingLanes));var f=e.pendingLanes;if(f===0&&(ur=null),X(r),n=n.stateNode,mt&&typeof mt.onCommitFiberRoot=="function")try{mt.onCommitFiberRoot(zt,n,void 0,(n.current.flags&128)===128)}catch{}if(l!==null){n=U.T,f=H.p,H.p=2,U.T=null;try{for(var h=e.onRecoverableError,E=0;E<l.length;E++){var M=l[E];h(M.value,{componentStack:M.stack})}}finally{U.T=n,H.p=f}}(Ua&3)!==0&&Ls(),pa(e),f=e.pendingLanes,(r&261930)!==0&&(f&42)!==0?e===V0?Gi++:(Gi=0,V0=e):Gi=0,Yi(0)}}function Jm(e,n){(e.pooledCacheLanes&=n)===0&&(n=e.pooledCache,n!=null&&(e.pooledCache=null,Ri(n)))}function Ls(){return Km(),Xm(),Zm(),Wm()}function Wm(){if(Vt!==5)return!1;var e=cr,n=B0;B0=0;var r=X(Ua),l=U.T,f=H.p;try{H.p=32>r?32:r,U.T=null,r=$0,$0=null;var h=cr,E=Ua;if(Vt=0,zo=cr=null,Ua=0,(nt&6)!==0)throw Error(i(331));var M=nt;if(nt|=4,jm(h.current),Om(h,h.current,E,r),nt=M,Yi(0,!1),mt&&typeof mt.onPostCommitFiberRoot=="function")try{mt.onPostCommitFiberRoot(zt,h)}catch{}return!0}finally{H.p=f,U.T=l,Jm(e,n)}}function ev(e,n,r){n=Fn(r,n),n=E0(e.stateNode,n,2),e=ar(e,n,2),e!==null&&(sa(e,2),pa(e))}function it(e,n,r){if(e.tag===3)ev(e,e,r);else for(;n!==null;){if(n.tag===3){ev(n,e,r);break}else if(n.tag===1){var l=n.stateNode;if(typeof n.type.getDerivedStateFromError=="function"||typeof l.componentDidCatch=="function"&&(ur===null||!ur.has(l))){e=Fn(r,e),r=tm(2),l=ar(n,r,2),l!==null&&(nm(r,l,n,e),sa(l,2),pa(l));break}}n=n.return}}function Y0(e,n,r){var l=e.pingCache;if(l===null){l=e.pingCache=new Q9;var f=new Set;l.set(n,f)}else f=l.get(n),f===void 0&&(f=new Set,l.set(n,f));f.has(r)||(P0=!0,f.add(r),e=W9.bind(null,e,n,r),n.then(e,e))}function W9(e,n,r){var l=e.pingCache;l!==null&&l.delete(n),e.pingedLanes|=e.suspendedLanes&r,e.warmLanes&=~r,ht===e&&(Ge&r)===r&&(Mt===4||Mt===3&&(Ge&62914560)===Ge&&300>kt()-Rs?(nt&2)===0&&Uo(e,0):I0|=r,ko===Ge&&(ko=0)),pa(e)}function tv(e,n){n===0&&(n=mi()),e=Fr(e,n),e!==null&&(sa(e,n),pa(e))}function e4(e){var n=e.memoizedState,r=0;n!==null&&(r=n.retryLane),tv(e,r)}function t4(e,n){var r=0;switch(e.tag){case 31:case 13:var l=e.stateNode,f=e.memoizedState;f!==null&&(r=f.retryLane);break;case 19:l=e.stateNode;break;case 22:l=e.stateNode._retryCache;break;default:throw Error(i(314))}l!==null&&l.delete(n),tv(e,r)}function n4(e,n){return On(e,n)}var js=null,Io=null,Q0=!1,Fs=!1,K0=!1,dr=0;function pa(e){e!==Io&&e.next===null&&(Io===null?js=Io=e:Io=Io.next=e),Fs=!0,Q0||(Q0=!0,r4())}function Yi(e,n){if(!K0&&Fs){K0=!0;do for(var r=!1,l=js;l!==null;){if(e!==0){var f=l.pendingLanes;if(f===0)var h=0;else{var E=l.suspendedLanes,M=l.pingedLanes;h=(1<<31-tn(42|e)+1)-1,h&=f&~(E&~M),h=h&201326741?h&201326741|1:h?h|2:0}h!==0&&(r=!0,ov(l,h))}else h=Ge,h=lo(l,l===ht?h:0,l.cancelPendingCommit!==null||l.timeoutHandle!==-1),(h&3)===0||Ya(l,h)||(r=!0,ov(l,h));l=l.next}while(r);K0=!1}}function a4(){nv()}function nv(){Fs=Q0=!1;var e=0;dr!==0&&p4()&&(e=dr);for(var n=kt(),r=null,l=js;l!==null;){var f=l.next,h=av(l,n);h===0?(l.next=null,r===null?js=f:r.next=f,f===null&&(Io=r)):(r=l,(e!==0||(h&3)!==0)&&(Fs=!0)),l=f}Vt!==0&&Vt!==5||Yi(e),dr!==0&&(dr=0)}function av(e,n){for(var r=e.suspendedLanes,l=e.pingedLanes,f=e.expirationTimes,h=e.pendingLanes&-62914561;0<h;){var E=31-tn(h),M=1<<E,k=f[E];k===-1?((M&r)===0||(M&l)!==0)&&(f[E]=hc(M,n)):k<=n&&(e.expiredLanes|=M),h&=~M}if(n=ht,r=Ge,r=lo(e,e===n?r:0,e.cancelPendingCommit!==null||e.timeoutHandle!==-1),l=e.callbackNode,r===0||e===n&&(ot===2||ot===9)||e.cancelPendingCommit!==null)return l!==null&&l!==null&&la(l),e.callbackNode=null,e.callbackPriority=0;if((r&3)===0||Ya(e,r)){if(n=r&-r,n===e.callbackPriority)return n;switch(l!==null&&la(l),X(r)){case 2:case 8:r=at;break;case 32:r=ve;break;case 268435456:r=He;break;default:r=ve}return l=rv.bind(null,e),r=On(r,l),e.callbackPriority=n,e.callbackNode=r,n}return l!==null&&l!==null&&la(l),e.callbackPriority=2,e.callbackNode=null,2}function rv(e,n){if(Vt!==0&&Vt!==5)return e.callbackNode=null,e.callbackPriority=0,null;var r=e.callbackNode;if(Ls()&&e.callbackNode!==r)return null;var l=Ge;return l=lo(e,e===ht?l:0,e.cancelPendingCommit!==null||e.timeoutHandle!==-1),l===0?null:(Pm(e,l,n),av(e,kt()),e.callbackNode!=null&&e.callbackNode===r?rv.bind(null,e):null)}function ov(e,n){if(Ls())return null;Pm(e,n,!0)}function r4(){v4(function(){(nt&6)!==0?On(ye,a4):nv()})}function X0(){if(dr===0){var e=wo;e===0&&(e=Tr,Tr<<=1,(Tr&261888)===0&&(Tr=256)),dr=e}return dr}function iv(e){return e==null||typeof e=="symbol"||typeof e=="boolean"?null:typeof e=="function"?e:$l(""+e)}function lv(e,n){var r=n.ownerDocument.createElement("input");return r.name=n.name,r.value=n.value,e.id&&r.setAttribute("form",e.id),n.parentNode.insertBefore(r,n),e=new FormData(e),r.parentNode.removeChild(r),e}function o4(e,n,r,l,f){if(n==="submit"&&r&&r.stateNode===f){var h=iv((f[be]||null).action),E=l.submitter;E&&(n=(n=E[be]||null)?iv(n.formAction):E.getAttribute("formAction"),n!==null&&(h=n,E=null));var M=new Yl("action","action",null,l,f);e.push({event:M,listeners:[{instance:null,listener:function(){if(l.defaultPrevented){if(dr!==0){var k=E?lv(f,E):new FormData(f);v0(r,{pending:!0,data:k,method:f.method,action:h},null,k)}}else typeof h=="function"&&(M.preventDefault(),k=E?lv(f,E):new FormData(f),v0(r,{pending:!0,data:k,method:f.method,action:h},h,k))},currentTarget:f}]})}}for(var Z0=0;Z0<Lc.length;Z0++){var J0=Lc[Z0],i4=J0.toLowerCase(),l4=J0[0].toUpperCase()+J0.slice(1);Jn(i4,"on"+l4)}Jn(Uh,"onAnimationEnd"),Jn(Ph,"onAnimationIteration"),Jn(Ih,"onAnimationStart"),Jn("dblclick","onDoubleClick"),Jn("focusin","onFocus"),Jn("focusout","onBlur"),Jn(S9,"onTransitionRun"),Jn(x9,"onTransitionStart"),Jn(w9,"onTransitionCancel"),Jn(Hh,"onTransitionEnd"),ua("onMouseEnter",["mouseout","mouseover"]),ua("onMouseLeave",["mouseout","mouseover"]),ua("onPointerEnter",["pointerout","pointerover"]),ua("onPointerLeave",["pointerout","pointerover"]),Gt("onChange","change click focusin focusout input keydown keyup selectionchange".split(" ")),Gt("onSelect","focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange".split(" ")),Gt("onBeforeInput",["compositionend","keypress","textInput","paste"]),Gt("onCompositionEnd","compositionend focusout keydown keypress keyup mousedown".split(" ")),Gt("onCompositionStart","compositionstart focusout keydown keypress keyup mousedown".split(" ")),Gt("onCompositionUpdate","compositionupdate focusout keydown keypress keyup mousedown".split(" "));var Qi="abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange resize seeked seeking stalled suspend timeupdate volumechange waiting".split(" "),s4=new Set("beforetoggle cancel close invalid load scroll scrollend toggle".split(" ").concat(Qi));function sv(e,n){n=(n&4)!==0;for(var r=0;r<e.length;r++){var l=e[r],f=l.event;l=l.listeners;e:{var h=void 0;if(n)for(var E=l.length-1;0<=E;E--){var M=l[E],k=M.instance,Q=M.currentTarget;if(M=M.listener,k!==h&&f.isPropagationStopped())break e;h=M,f.currentTarget=Q;try{h(f)}catch(ae){Xl(ae)}f.currentTarget=null,h=k}else for(E=0;E<l.length;E++){if(M=l[E],k=M.instance,Q=M.currentTarget,M=M.listener,k!==h&&f.isPropagationStopped())break e;h=M,f.currentTarget=Q;try{h(f)}catch(ae){Xl(ae)}f.currentTarget=null,h=k}}}}function qe(e,n){var r=n[Ee];r===void 0&&(r=n[Ee]=new Set);var l=e+"__bubble";r.has(l)||(uv(n,e,2,!1),r.add(l))}function W0(e,n,r){var l=0;n&&(l|=4),uv(r,e,l,n)}var ks="_reactListening"+Math.random().toString(36).slice(2);function e2(e){if(!e[ks]){e[ks]=!0,Ka.forEach(function(r){r!=="selectionchange"&&(s4.has(r)||W0(r,!1,e),W0(r,!0,e))});var n=e.nodeType===9?e:e.ownerDocument;n===null||n[ks]||(n[ks]=!0,W0("selectionchange",!1,n))}}function uv(e,n,r,l){switch(Uv(n)){case 2:var f=k4;break;case 8:f=z4;break;default:f=m2}r=f.bind(null,n,r,e),f=void 0,!Cc||n!=="touchstart"&&n!=="touchmove"&&n!=="wheel"||(f=!0),l?f!==void 0?e.addEventListener(n,r,{capture:!0,passive:f}):e.addEventListener(n,r,!0):f!==void 0?e.addEventListener(n,r,{passive:f}):e.addEventListener(n,r,!1)}function t2(e,n,r,l,f){var h=l;if((n&1)===0&&(n&2)===0&&l!==null)e:for(;;){if(l===null)return;var E=l.tag;if(E===3||E===4){var M=l.stateNode.containerInfo;if(M===f)break;if(E===4)for(E=l.return;E!==null;){var k=E.tag;if((k===3||k===4)&&E.stateNode.containerInfo===f)return;E=E.return}for(;M!==null;){if(E=Ct(M),E===null)return;if(k=E.tag,k===5||k===6||k===26||k===27){l=h=E;continue e}M=M.parentNode}}l=l.return}ph(function(){var Q=h,ae=yc(r),le=[];e:{var Z=Bh.get(e);if(Z!==void 0){var ee=Yl,xe=e;switch(e){case"keypress":if(ql(r)===0)break e;case"keydown":case"keyup":ee=t9;break;case"focusin":xe="focus",ee=xc;break;case"focusout":xe="blur",ee=xc;break;case"beforeblur":case"afterblur":ee=xc;break;case"click":if(r.button===2)break e;case"auxclick":case"dblclick":case"mousedown":case"mousemove":case"mouseup":case"mouseout":case"mouseover":case"contextmenu":ee=gh;break;case"drag":case"dragend":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"dragstart":case"drop":ee=$6;break;case"touchcancel":case"touchend":case"touchmove":case"touchstart":ee=r9;break;case Uh:case Ph:case Ih:ee=G6;break;case Hh:ee=i9;break;case"scroll":case"scrollend":ee=H6;break;case"wheel":ee=s9;break;case"copy":case"cut":case"paste":ee=Q6;break;case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointermove":case"pointerout":case"pointerover":case"pointerup":ee=Ah;break;case"toggle":case"beforetoggle":ee=c9}var Le=(n&4)!==0,ct=!Le&&(e==="scroll"||e==="scrollend"),V=Le?Z!==null?Z+"Capture":null:Z;Le=[];for(var P=Q,Y;P!==null;){var oe=P;if(Y=oe.stateNode,oe=oe.tag,oe!==5&&oe!==26&&oe!==27||Y===null||V===null||(oe=vi(P,V),oe!=null&&Le.push(Ki(P,oe,Y))),ct)break;P=P.return}0<Le.length&&(Z=new ee(Z,xe,null,r,ae),le.push({event:Z,listeners:Le}))}}if((n&7)===0){e:{if(Z=e==="mouseover"||e==="pointerover",ee=e==="mouseout"||e==="pointerout",Z&&r!==gc&&(xe=r.relatedTarget||r.fromElement)&&(Ct(xe)||xe[Te]))break e;if((ee||Z)&&(Z=ae.window===ae?ae:(Z=ae.ownerDocument)?Z.defaultView||Z.parentWindow:window,ee?(xe=r.relatedTarget||r.toElement,ee=Q,xe=xe?Ct(xe):null,xe!==null&&(ct=u(xe),Le=xe.tag,xe!==ct||Le!==5&&Le!==27&&Le!==6)&&(xe=null)):(ee=null,xe=Q),ee!==xe)){if(Le=gh,oe="onMouseLeave",V="onMouseEnter",P="mouse",(e==="pointerout"||e==="pointerover")&&(Le=Ah,oe="onPointerLeave",V="onPointerEnter",P="pointer"),ct=ee==null?Z:Ke(ee),Y=xe==null?Z:Ke(xe),Z=new Le(oe,P+"leave",ee,r,ae),Z.target=ct,Z.relatedTarget=Y,oe=null,Ct(ae)===Q&&(Le=new Le(V,P+"enter",xe,r,ae),Le.target=Y,Le.relatedTarget=ct,oe=Le),ct=oe,ee&&xe)t:{for(Le=u4,V=ee,P=xe,Y=0,oe=V;oe;oe=Le(oe))Y++;oe=0;for(var Oe=P;Oe;Oe=Le(Oe))oe++;for(;0<Y-oe;)V=Le(V),Y--;for(;0<oe-Y;)P=Le(P),oe--;for(;Y--;){if(V===P||P!==null&&V===P.alternate){Le=V;break t}V=Le(V),P=Le(P)}Le=null}else Le=null;ee!==null&&cv(le,Z,ee,Le,!1),xe!==null&&ct!==null&&cv(le,ct,xe,Le,!0)}}e:{if(Z=Q?Ke(Q):window,ee=Z.nodeName&&Z.nodeName.toLowerCase(),ee==="select"||ee==="input"&&Z.type==="file")var et=Rh;else if(wh(Z))if(Th)et=C9;else{et=y9;var Me=g9}else ee=Z.nodeName,!ee||ee.toLowerCase()!=="input"||Z.type!=="checkbox"&&Z.type!=="radio"?Q&&vc(Q.elementType)&&(et=Rh):et=A9;if(et&&(et=et(e,Q))){_h(le,et,r,ae);break e}Me&&Me(e,Z,Q),e==="focusout"&&Q&&Z.type==="number"&&Q.memoizedProps.value!=null&&mc(Z,"number",Z.value)}switch(Me=Q?Ke(Q):window,e){case"focusin":(wh(Me)||Me.contentEditable==="true")&&(go=Me,Dc=Q,xi=null);break;case"focusout":xi=Dc=go=null;break;case"mousedown":Oc=!0;break;case"contextmenu":case"mouseup":case"dragend":Oc=!1,kh(le,r,ae);break;case"selectionchange":if(E9)break;case"keydown":case"keyup":kh(le,r,ae)}var Pe;if(_c)e:{switch(e){case"compositionstart":var Ye="onCompositionStart";break e;case"compositionend":Ye="onCompositionEnd";break e;case"compositionupdate":Ye="onCompositionUpdate";break e}Ye=void 0}else vo?Sh(e,r)&&(Ye="onCompositionEnd"):e==="keydown"&&r.keyCode===229&&(Ye="onCompositionStart");Ye&&(Ch&&r.locale!=="ko"&&(vo||Ye!=="onCompositionStart"?Ye==="onCompositionEnd"&&vo&&(Pe=mh()):(Xa=ae,bc="value"in Xa?Xa.value:Xa.textContent,vo=!0)),Me=zs(Q,Ye),0<Me.length&&(Ye=new yh(Ye,e,null,r,ae),le.push({event:Ye,listeners:Me}),Pe?Ye.data=Pe:(Pe=xh(r),Pe!==null&&(Ye.data=Pe)))),(Pe=d9?h9(e,r):p9(e,r))&&(Ye=zs(Q,"onBeforeInput"),0<Ye.length&&(Me=new yh("onBeforeInput","beforeinput",null,r,ae),le.push({event:Me,listeners:Ye}),Me.data=Pe)),o4(le,e,Q,r,ae)}sv(le,n)})}function Ki(e,n,r){return{instance:e,listener:n,currentTarget:r}}function zs(e,n){for(var r=n+"Capture",l=[];e!==null;){var f=e,h=f.stateNode;if(f=f.tag,f!==5&&f!==26&&f!==27||h===null||(f=vi(e,r),f!=null&&l.unshift(Ki(e,f,h)),f=vi(e,n),f!=null&&l.push(Ki(e,f,h))),e.tag===3)return l;e=e.return}return[]}function u4(e){if(e===null)return null;do e=e.return;while(e&&e.tag!==5&&e.tag!==27);return e||null}function cv(e,n,r,l,f){for(var h=n._reactName,E=[];r!==null&&r!==l;){var M=r,k=M.alternate,Q=M.stateNode;if(M=M.tag,k!==null&&k===l)break;M!==5&&M!==26&&M!==27||Q===null||(k=Q,f?(Q=vi(r,h),Q!=null&&E.unshift(Ki(r,Q,k))):f||(Q=vi(r,h),Q!=null&&E.push(Ki(r,Q,k)))),r=r.return}E.length!==0&&e.push({event:n,listeners:E})}var c4=/\r\n?/g,f4=/\u0000|\uFFFD/g;function fv(e){return(typeof e=="string"?e:""+e).replace(c4,` |
|
| 10 | + | `).replace(f4,"")}function dv(e,n){return n=fv(n),fv(e)===n}function ut(e,n,r,l,f,h){switch(r){case"children":typeof l=="string"?n==="body"||n==="textarea"&&l===""||ho(e,l):(typeof l=="number"||typeof l=="bigint")&&n!=="body"&&ho(e,""+l);break;case"className":Nt(e,"class",l);break;case"tabIndex":Nt(e,"tabindex",l);break;case"dir":case"role":case"viewBox":case"width":case"height":Nt(e,r,l);break;case"style":dh(e,l,h);break;case"data":if(n!=="object"){Nt(e,"data",l);break}case"src":case"href":if(l===""&&(n!=="a"||r!=="href")){e.removeAttribute(r);break}if(l==null||typeof l=="function"||typeof l=="symbol"||typeof l=="boolean"){e.removeAttribute(r);break}l=$l(""+l),e.setAttribute(r,l);break;case"action":case"formAction":if(typeof l=="function"){e.setAttribute(r,"javascript:throw new Error('A React form was unexpectedly submitted. If you called form.submit() manually, consider using form.requestSubmit() instead. If you\\'re trying to use event.stopPropagation() in a submit event handler, consider also calling event.preventDefault().')");break}else typeof h=="function"&&(r==="formAction"?(n!=="input"&&ut(e,n,"name",f.name,f,null),ut(e,n,"formEncType",f.formEncType,f,null),ut(e,n,"formMethod",f.formMethod,f,null),ut(e,n,"formTarget",f.formTarget,f,null)):(ut(e,n,"encType",f.encType,f,null),ut(e,n,"method",f.method,f,null),ut(e,n,"target",f.target,f,null)));if(l==null||typeof l=="symbol"||typeof l=="boolean"){e.removeAttribute(r);break}l=$l(""+l),e.setAttribute(r,l);break;case"onClick":l!=null&&(e.onclick=Sa);break;case"onScroll":l!=null&&qe("scroll",e);break;case"onScrollEnd":l!=null&&qe("scrollend",e);break;case"dangerouslySetInnerHTML":if(l!=null){if(typeof l!="object"||!("__html"in l))throw Error(i(61));if(r=l.__html,r!=null){if(f.children!=null)throw Error(i(60));e.innerHTML=r}}break;case"multiple":e.multiple=l&&typeof l!="function"&&typeof l!="symbol";break;case"muted":e.muted=l&&typeof l!="function"&&typeof l!="symbol";break;case"suppressContentEditableWarning":case"suppressHydrationWarning":case"defaultValue":case"defaultChecked":case"innerHTML":case"ref":break;case"autoFocus":break;case"xlinkHref":if(l==null||typeof l=="function"||typeof l=="boolean"||typeof l=="symbol"){e.removeAttribute("xlink:href");break}r=$l(""+l),e.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",r);break;case"contentEditable":case"spellCheck":case"draggable":case"value":case"autoReverse":case"externalResourcesRequired":case"focusable":case"preserveAlpha":l!=null&&typeof l!="function"&&typeof l!="symbol"?e.setAttribute(r,""+l):e.removeAttribute(r);break;case"inert":case"allowFullScreen":case"async":case"autoPlay":case"controls":case"default":case"defer":case"disabled":case"disablePictureInPicture":case"disableRemotePlayback":case"formNoValidate":case"hidden":case"loop":case"noModule":case"noValidate":case"open":case"playsInline":case"readOnly":case"required":case"reversed":case"scoped":case"seamless":case"itemScope":l&&typeof l!="function"&&typeof l!="symbol"?e.setAttribute(r,""):e.removeAttribute(r);break;case"capture":case"download":l===!0?e.setAttribute(r,""):l!==!1&&l!=null&&typeof l!="function"&&typeof l!="symbol"?e.setAttribute(r,l):e.removeAttribute(r);break;case"cols":case"rows":case"size":case"span":l!=null&&typeof l!="function"&&typeof l!="symbol"&&!isNaN(l)&&1<=l?e.setAttribute(r,l):e.removeAttribute(r);break;case"rowSpan":case"start":l==null||typeof l=="function"||typeof l=="symbol"||isNaN(l)?e.removeAttribute(r):e.setAttribute(r,l);break;case"popover":qe("beforetoggle",e),qe("toggle",e),$e(e,"popover",l);break;case"xlinkActuate":nn(e,"http://www.w3.org/1999/xlink","xlink:actuate",l);break;case"xlinkArcrole":nn(e,"http://www.w3.org/1999/xlink","xlink:arcrole",l);break;case"xlinkRole":nn(e,"http://www.w3.org/1999/xlink","xlink:role",l);break;case"xlinkShow":nn(e,"http://www.w3.org/1999/xlink","xlink:show",l);break;case"xlinkTitle":nn(e,"http://www.w3.org/1999/xlink","xlink:title",l);break;case"xlinkType":nn(e,"http://www.w3.org/1999/xlink","xlink:type",l);break;case"xmlBase":nn(e,"http://www.w3.org/XML/1998/namespace","xml:base",l);break;case"xmlLang":nn(e,"http://www.w3.org/XML/1998/namespace","xml:lang",l);break;case"xmlSpace":nn(e,"http://www.w3.org/XML/1998/namespace","xml:space",l);break;case"is":$e(e,"is",l);break;case"innerText":case"textContent":break;default:(!(2<r.length)||r[0]!=="o"&&r[0]!=="O"||r[1]!=="n"&&r[1]!=="N")&&(r=P6.get(r)||r,$e(e,r,l))}}function n2(e,n,r,l,f,h){switch(r){case"style":dh(e,l,h);break;case"dangerouslySetInnerHTML":if(l!=null){if(typeof l!="object"||!("__html"in l))throw Error(i(61));if(r=l.__html,r!=null){if(f.children!=null)throw Error(i(60));e.innerHTML=r}}break;case"children":typeof l=="string"?ho(e,l):(typeof l=="number"||typeof l=="bigint")&&ho(e,""+l);break;case"onScroll":l!=null&&qe("scroll",e);break;case"onScrollEnd":l!=null&&qe("scrollend",e);break;case"onClick":l!=null&&(e.onclick=Sa);break;case"suppressContentEditableWarning":case"suppressHydrationWarning":case"innerHTML":case"ref":break;case"innerText":case"textContent":break;default:if(!Zn.hasOwnProperty(r))e:{if(r[0]==="o"&&r[1]==="n"&&(f=r.endsWith("Capture"),n=r.slice(2,f?r.length-7:void 0),h=e[be]||null,h=h!=null?h[r]:null,typeof h=="function"&&e.removeEventListener(n,h,f),typeof l=="function")){typeof h!="function"&&h!==null&&(r in e?e[r]=null:e.hasAttribute(r)&&e.removeAttribute(r)),e.addEventListener(n,l,f);break e}r in e?e[r]=l:l===!0?e.setAttribute(r,""):$e(e,r,l)}}}function Jt(e,n,r){switch(n){case"div":case"span":case"svg":case"path":case"a":case"g":case"p":case"li":break;case"img":qe("error",e),qe("load",e);var l=!1,f=!1,h;for(h in r)if(r.hasOwnProperty(h)){var E=r[h];if(E!=null)switch(h){case"src":l=!0;break;case"srcSet":f=!0;break;case"children":case"dangerouslySetInnerHTML":throw Error(i(137,n));default:ut(e,n,h,E,r,null)}}f&&ut(e,n,"srcSet",r.srcSet,r,null),l&&ut(e,n,"src",r.src,r,null);return;case"input":qe("invalid",e);var M=h=E=f=null,k=null,Q=null;for(l in r)if(r.hasOwnProperty(l)){var ae=r[l];if(ae!=null)switch(l){case"name":f=ae;break;case"type":E=ae;break;case"checked":k=ae;break;case"defaultChecked":Q=ae;break;case"value":h=ae;break;case"defaultValue":M=ae;break;case"children":case"dangerouslySetInnerHTML":if(ae!=null)throw Error(i(137,n));break;default:ut(e,n,l,ae,r,null)}}sh(e,h,M,k,Q,E,f,!1);return;case"select":qe("invalid",e),l=E=h=null;for(f in r)if(r.hasOwnProperty(f)&&(M=r[f],M!=null))switch(f){case"value":h=M;break;case"defaultValue":E=M;break;case"multiple":l=M;default:ut(e,n,f,M,r,null)}n=h,r=E,e.multiple=!!l,n!=null?fo(e,!!l,n,!1):r!=null&&fo(e,!!l,r,!0);return;case"textarea":qe("invalid",e),h=f=l=null;for(E in r)if(r.hasOwnProperty(E)&&(M=r[E],M!=null))switch(E){case"value":l=M;break;case"defaultValue":f=M;break;case"children":h=M;break;case"dangerouslySetInnerHTML":if(M!=null)throw Error(i(91));break;default:ut(e,n,E,M,r,null)}ch(e,l,f,h);return;case"option":for(k in r)r.hasOwnProperty(k)&&(l=r[k],l!=null)&&(k==="selected"?e.selected=l&&typeof l!="function"&&typeof l!="symbol":ut(e,n,k,l,r,null));return;case"dialog":qe("beforetoggle",e),qe("toggle",e),qe("cancel",e),qe("close",e);break;case"iframe":case"object":qe("load",e);break;case"video":case"audio":for(l=0;l<Qi.length;l++)qe(Qi[l],e);break;case"image":qe("error",e),qe("load",e);break;case"details":qe("toggle",e);break;case"embed":case"source":case"link":qe("error",e),qe("load",e);case"area":case"base":case"br":case"col":case"hr":case"keygen":case"meta":case"param":case"track":case"wbr":case"menuitem":for(Q in r)if(r.hasOwnProperty(Q)&&(l=r[Q],l!=null))switch(Q){case"children":case"dangerouslySetInnerHTML":throw Error(i(137,n));default:ut(e,n,Q,l,r,null)}return;default:if(vc(n)){for(ae in r)r.hasOwnProperty(ae)&&(l=r[ae],l!==void 0&&n2(e,n,ae,l,r,void 0));return}}for(M in r)r.hasOwnProperty(M)&&(l=r[M],l!=null&&ut(e,n,M,l,r,null))}function d4(e,n,r,l){switch(n){case"div":case"span":case"svg":case"path":case"a":case"g":case"p":case"li":break;case"input":var f=null,h=null,E=null,M=null,k=null,Q=null,ae=null;for(ee in r){var le=r[ee];if(r.hasOwnProperty(ee)&&le!=null)switch(ee){case"checked":break;case"value":break;case"defaultValue":k=le;default:l.hasOwnProperty(ee)||ut(e,n,ee,null,l,le)}}for(var Z in l){var ee=l[Z];if(le=r[Z],l.hasOwnProperty(Z)&&(ee!=null||le!=null))switch(Z){case"type":h=ee;break;case"name":f=ee;break;case"checked":Q=ee;break;case"defaultChecked":ae=ee;break;case"value":E=ee;break;case"defaultValue":M=ee;break;case"children":case"dangerouslySetInnerHTML":if(ee!=null)throw Error(i(137,n));break;default:ee!==le&&ut(e,n,Z,ee,l,le)}}pc(e,E,M,k,Q,ae,h,f);return;case"select":ee=E=M=Z=null;for(h in r)if(k=r[h],r.hasOwnProperty(h)&&k!=null)switch(h){case"value":break;case"multiple":ee=k;default:l.hasOwnProperty(h)||ut(e,n,h,null,l,k)}for(f in l)if(h=l[f],k=r[f],l.hasOwnProperty(f)&&(h!=null||k!=null))switch(f){case"value":Z=h;break;case"defaultValue":M=h;break;case"multiple":E=h;default:h!==k&&ut(e,n,f,h,l,k)}n=M,r=E,l=ee,Z!=null?fo(e,!!r,Z,!1):!!l!=!!r&&(n!=null?fo(e,!!r,n,!0):fo(e,!!r,r?[]:"",!1));return;case"textarea":ee=Z=null;for(M in r)if(f=r[M],r.hasOwnProperty(M)&&f!=null&&!l.hasOwnProperty(M))switch(M){case"value":break;case"children":break;default:ut(e,n,M,null,l,f)}for(E in l)if(f=l[E],h=r[E],l.hasOwnProperty(E)&&(f!=null||h!=null))switch(E){case"value":Z=f;break;case"defaultValue":ee=f;break;case"children":break;case"dangerouslySetInnerHTML":if(f!=null)throw Error(i(91));break;default:f!==h&&ut(e,n,E,f,l,h)}uh(e,Z,ee);return;case"option":for(var xe in r)Z=r[xe],r.hasOwnProperty(xe)&&Z!=null&&!l.hasOwnProperty(xe)&&(xe==="selected"?e.selected=!1:ut(e,n,xe,null,l,Z));for(k in l)Z=l[k],ee=r[k],l.hasOwnProperty(k)&&Z!==ee&&(Z!=null||ee!=null)&&(k==="selected"?e.selected=Z&&typeof Z!="function"&&typeof Z!="symbol":ut(e,n,k,Z,l,ee));return;case"img":case"link":case"area":case"base":case"br":case"col":case"embed":case"hr":case"keygen":case"meta":case"param":case"source":case"track":case"wbr":case"menuitem":for(var Le in r)Z=r[Le],r.hasOwnProperty(Le)&&Z!=null&&!l.hasOwnProperty(Le)&&ut(e,n,Le,null,l,Z);for(Q in l)if(Z=l[Q],ee=r[Q],l.hasOwnProperty(Q)&&Z!==ee&&(Z!=null||ee!=null))switch(Q){case"children":case"dangerouslySetInnerHTML":if(Z!=null)throw Error(i(137,n));break;default:ut(e,n,Q,Z,l,ee)}return;default:if(vc(n)){for(var ct in r)Z=r[ct],r.hasOwnProperty(ct)&&Z!==void 0&&!l.hasOwnProperty(ct)&&n2(e,n,ct,void 0,l,Z);for(ae in l)Z=l[ae],ee=r[ae],!l.hasOwnProperty(ae)||Z===ee||Z===void 0&&ee===void 0||n2(e,n,ae,Z,l,ee);return}}for(var V in r)Z=r[V],r.hasOwnProperty(V)&&Z!=null&&!l.hasOwnProperty(V)&&ut(e,n,V,null,l,Z);for(le in l)Z=l[le],ee=r[le],!l.hasOwnProperty(le)||Z===ee||Z==null&&ee==null||ut(e,n,le,Z,l,ee)}function hv(e){switch(e){case"css":case"script":case"font":case"img":case"image":case"input":case"link":return!0;default:return!1}}function h4(){if(typeof performance.getEntriesByType=="function"){for(var e=0,n=0,r=performance.getEntriesByType("resource"),l=0;l<r.length;l++){var f=r[l],h=f.transferSize,E=f.initiatorType,M=f.duration;if(h&&M&&hv(E)){for(E=0,M=f.responseEnd,l+=1;l<r.length;l++){var k=r[l],Q=k.startTime;if(Q>M)break;var ae=k.transferSize,le=k.initiatorType;ae&&hv(le)&&(k=k.responseEnd,E+=ae*(k<M?1:(M-Q)/(k-Q)))}if(--l,n+=8*(h+E)/(f.duration/1e3),e++,10<e)break}}if(0<e)return n/e/1e6}return navigator.connection&&(e=navigator.connection.downlink,typeof e=="number")?e:5}var a2=null,r2=null;function Us(e){return e.nodeType===9?e:e.ownerDocument}function pv(e){switch(e){case"http://www.w3.org/2000/svg":return 1;case"http://www.w3.org/1998/Math/MathML":return 2;default:return 0}}function mv(e,n){if(e===0)switch(n){case"svg":return 1;case"math":return 2;default:return 0}return e===1&&n==="foreignObject"?0:e}function o2(e,n){return e==="textarea"||e==="noscript"||typeof n.children=="string"||typeof n.children=="number"||typeof n.children=="bigint"||typeof n.dangerouslySetInnerHTML=="object"&&n.dangerouslySetInnerHTML!==null&&n.dangerouslySetInnerHTML.__html!=null}var i2=null;function p4(){var e=window.event;return e&&e.type==="popstate"?e===i2?!1:(i2=e,!0):(i2=null,!1)}var vv=typeof setTimeout=="function"?setTimeout:void 0,m4=typeof clearTimeout=="function"?clearTimeout:void 0,gv=typeof Promise=="function"?Promise:void 0,v4=typeof queueMicrotask=="function"?queueMicrotask:typeof gv<"u"?function(e){return gv.resolve(null).then(e).catch(g4)}:vv;function g4(e){setTimeout(function(){throw e})}function hr(e){return e==="head"}function yv(e,n){var r=n,l=0;do{var f=r.nextSibling;if(e.removeChild(r),f&&f.nodeType===8)if(r=f.data,r==="/$"||r==="/&"){if(l===0){e.removeChild(f),Vo(n);return}l--}else if(r==="$"||r==="$?"||r==="$~"||r==="$!"||r==="&")l++;else if(r==="html")Xi(e.ownerDocument.documentElement);else if(r==="head"){r=e.ownerDocument.head,Xi(r);for(var h=r.firstChild;h;){var E=h.nextSibling,M=h.nodeName;h[Be]||M==="SCRIPT"||M==="STYLE"||M==="LINK"&&h.rel.toLowerCase()==="stylesheet"||r.removeChild(h),h=E}}else r==="body"&&Xi(e.ownerDocument.body);r=f}while(r);Vo(n)}function Av(e,n){var r=e;e=0;do{var l=r.nextSibling;if(r.nodeType===1?n?(r._stashedDisplay=r.style.display,r.style.display="none"):(r.style.display=r._stashedDisplay||"",r.getAttribute("style")===""&&r.removeAttribute("style")):r.nodeType===3&&(n?(r._stashedText=r.nodeValue,r.nodeValue=""):r.nodeValue=r._stashedText||""),l&&l.nodeType===8)if(r=l.data,r==="/$"){if(e===0)break;e--}else r!=="$"&&r!=="$?"&&r!=="$~"&&r!=="$!"||e++;r=l}while(r)}function l2(e){var n=e.firstChild;for(n&&n.nodeType===10&&(n=n.nextSibling);n;){var r=n;switch(n=n.nextSibling,r.nodeName){case"HTML":case"HEAD":case"BODY":l2(r),dt(r);continue;case"SCRIPT":case"STYLE":continue;case"LINK":if(r.rel.toLowerCase()==="stylesheet")continue}e.removeChild(r)}}function y4(e,n,r,l){for(;e.nodeType===1;){var f=r;if(e.nodeName.toLowerCase()!==n.toLowerCase()){if(!l&&(e.nodeName!=="INPUT"||e.type!=="hidden"))break}else if(l){if(!e[Be])switch(n){case"meta":if(!e.hasAttribute("itemprop"))break;return e;case"link":if(h=e.getAttribute("rel"),h==="stylesheet"&&e.hasAttribute("data-precedence"))break;if(h!==f.rel||e.getAttribute("href")!==(f.href==null||f.href===""?null:f.href)||e.getAttribute("crossorigin")!==(f.crossOrigin==null?null:f.crossOrigin)||e.getAttribute("title")!==(f.title==null?null:f.title))break;return e;case"style":if(e.hasAttribute("data-precedence"))break;return e;case"script":if(h=e.getAttribute("src"),(h!==(f.src==null?null:f.src)||e.getAttribute("type")!==(f.type==null?null:f.type)||e.getAttribute("crossorigin")!==(f.crossOrigin==null?null:f.crossOrigin))&&h&&e.hasAttribute("async")&&!e.hasAttribute("itemprop"))break;return e;default:return e}}else if(n==="input"&&e.type==="hidden"){var h=f.name==null?null:""+f.name;if(f.type==="hidden"&&e.getAttribute("name")===h)return e}else return e;if(e=In(e.nextSibling),e===null)break}return null}function A4(e,n,r){if(n==="")return null;for(;e.nodeType!==3;)if((e.nodeType!==1||e.nodeName!=="INPUT"||e.type!=="hidden")&&!r||(e=In(e.nextSibling),e===null))return null;return e}function Cv(e,n){for(;e.nodeType!==8;)if((e.nodeType!==1||e.nodeName!=="INPUT"||e.type!=="hidden")&&!n||(e=In(e.nextSibling),e===null))return null;return e}function s2(e){return e.data==="$?"||e.data==="$~"}function u2(e){return e.data==="$!"||e.data==="$?"&&e.ownerDocument.readyState!=="loading"}function C4(e,n){var r=e.ownerDocument;if(e.data==="$~")e._reactRetry=n;else if(e.data!=="$?"||r.readyState!=="loading")n();else{var l=function(){n(),r.removeEventListener("DOMContentLoaded",l)};r.addEventListener("DOMContentLoaded",l),e._reactRetry=l}}function In(e){for(;e!=null;e=e.nextSibling){var n=e.nodeType;if(n===1||n===3)break;if(n===8){if(n=e.data,n==="$"||n==="$!"||n==="$?"||n==="$~"||n==="&"||n==="F!"||n==="F")break;if(n==="/$"||n==="/&")return null}}return e}var c2=null;function bv(e){e=e.nextSibling;for(var n=0;e;){if(e.nodeType===8){var r=e.data;if(r==="/$"||r==="/&"){if(n===0)return In(e.nextSibling);n--}else r!=="$"&&r!=="$!"&&r!=="$?"&&r!=="$~"&&r!=="&"||n++}e=e.nextSibling}return null}function Ev(e){e=e.previousSibling;for(var n=0;e;){if(e.nodeType===8){var r=e.data;if(r==="$"||r==="$!"||r==="$?"||r==="$~"||r==="&"){if(n===0)return e;n--}else r!=="/$"&&r!=="/&"||n++}e=e.previousSibling}return null}function Sv(e,n,r){switch(n=Us(r),e){case"html":if(e=n.documentElement,!e)throw Error(i(452));return e;case"head":if(e=n.head,!e)throw Error(i(453));return e;case"body":if(e=n.body,!e)throw Error(i(454));return e;default:throw Error(i(451))}}function Xi(e){for(var n=e.attributes;n.length;)e.removeAttributeNode(n[0]);dt(e)}var Hn=new Map,xv=new Set;function Ps(e){return typeof e.getRootNode=="function"?e.getRootNode():e.nodeType===9?e:e.ownerDocument}var Pa=H.d;H.d={f:b4,r:E4,D:S4,C:x4,L:w4,m:_4,X:T4,S:R4,M:M4};function b4(){var e=Pa.f(),n=Ds();return e||n}function E4(e){var n=Rt(e);n!==null&&n.tag===5&&n.type==="form"?Hp(n):Pa.r(e)}var Ho=typeof document>"u"?null:document;function wv(e,n,r){var l=Ho;if(l&&typeof n=="string"&&n){var f=Ln(n);f='link[rel="'+e+'"][href="'+f+'"]',typeof r=="string"&&(f+='[crossorigin="'+r+'"]'),xv.has(f)||(xv.add(f),e={rel:e,crossOrigin:r,href:n},l.querySelector(f)===null&&(n=l.createElement("link"),Jt(n,"link",e),vt(n),l.head.appendChild(n)))}}function S4(e){Pa.D(e),wv("dns-prefetch",e,null)}function x4(e,n){Pa.C(e,n),wv("preconnect",e,n)}function w4(e,n,r){Pa.L(e,n,r);var l=Ho;if(l&&e&&n){var f='link[rel="preload"][as="'+Ln(n)+'"]';n==="image"&&r&&r.imageSrcSet?(f+='[imagesrcset="'+Ln(r.imageSrcSet)+'"]',typeof r.imageSizes=="string"&&(f+='[imagesizes="'+Ln(r.imageSizes)+'"]')):f+='[href="'+Ln(e)+'"]';var h=f;switch(n){case"style":h=Bo(e);break;case"script":h=$o(e)}Hn.has(h)||(e=p({rel:"preload",href:n==="image"&&r&&r.imageSrcSet?void 0:e,as:n},r),Hn.set(h,e),l.querySelector(f)!==null||n==="style"&&l.querySelector(Zi(h))||n==="script"&&l.querySelector(Ji(h))||(n=l.createElement("link"),Jt(n,"link",e),vt(n),l.head.appendChild(n)))}}function _4(e,n){Pa.m(e,n);var r=Ho;if(r&&e){var l=n&&typeof n.as=="string"?n.as:"script",f='link[rel="modulepreload"][as="'+Ln(l)+'"][href="'+Ln(e)+'"]',h=f;switch(l){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":h=$o(e)}if(!Hn.has(h)&&(e=p({rel:"modulepreload",href:e},n),Hn.set(h,e),r.querySelector(f)===null)){switch(l){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(r.querySelector(Ji(h)))return}l=r.createElement("link"),Jt(l,"link",e),vt(l),r.head.appendChild(l)}}}function R4(e,n,r){Pa.S(e,n,r);var l=Ho;if(l&&e){var f=Ut(l).hoistableStyles,h=Bo(e);n=n||"default";var E=f.get(h);if(!E){var M={loading:0,preload:null};if(E=l.querySelector(Zi(h)))M.loading=5;else{e=p({rel:"stylesheet",href:e,"data-precedence":n},r),(r=Hn.get(h))&&f2(e,r);var k=E=l.createElement("link");vt(k),Jt(k,"link",e),k._p=new Promise(function(Q,ae){k.onload=Q,k.onerror=ae}),k.addEventListener("load",function(){M.loading|=1}),k.addEventListener("error",function(){M.loading|=2}),M.loading|=4,Is(E,n,l)}E={type:"stylesheet",instance:E,count:1,state:M},f.set(h,E)}}}function T4(e,n){Pa.X(e,n);var r=Ho;if(r&&e){var l=Ut(r).hoistableScripts,f=$o(e),h=l.get(f);h||(h=r.querySelector(Ji(f)),h||(e=p({src:e,async:!0},n),(n=Hn.get(f))&&d2(e,n),h=r.createElement("script"),vt(h),Jt(h,"link",e),r.head.appendChild(h)),h={type:"script",instance:h,count:1,state:null},l.set(f,h))}}function M4(e,n){Pa.M(e,n);var r=Ho;if(r&&e){var l=Ut(r).hoistableScripts,f=$o(e),h=l.get(f);h||(h=r.querySelector(Ji(f)),h||(e=p({src:e,async:!0,type:"module"},n),(n=Hn.get(f))&&d2(e,n),h=r.createElement("script"),vt(h),Jt(h,"link",e),r.head.appendChild(h)),h={type:"script",instance:h,count:1,state:null},l.set(f,h))}}function _v(e,n,r,l){var f=(f=Se.current)?Ps(f):null;if(!f)throw Error(i(446));switch(e){case"meta":case"title":return null;case"style":return typeof r.precedence=="string"&&typeof r.href=="string"?(n=Bo(r.href),r=Ut(f).hoistableStyles,l=r.get(n),l||(l={type:"style",instance:null,count:0,state:null},r.set(n,l)),l):{type:"void",instance:null,count:0,state:null};case"link":if(r.rel==="stylesheet"&&typeof r.href=="string"&&typeof r.precedence=="string"){e=Bo(r.href);var h=Ut(f).hoistableStyles,E=h.get(e);if(E||(f=f.ownerDocument||f,E={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},h.set(e,E),(h=f.querySelector(Zi(e)))&&!h._p&&(E.instance=h,E.state.loading=5),Hn.has(e)||(r={rel:"preload",as:"style",href:r.href,crossOrigin:r.crossOrigin,integrity:r.integrity,media:r.media,hrefLang:r.hrefLang,referrerPolicy:r.referrerPolicy},Hn.set(e,r),h||D4(f,e,r,E.state))),n&&l===null)throw Error(i(528,""));return E}if(n&&l!==null)throw Error(i(529,""));return null;case"script":return n=r.async,r=r.src,typeof r=="string"&&n&&typeof n!="function"&&typeof n!="symbol"?(n=$o(r),r=Ut(f).hoistableScripts,l=r.get(n),l||(l={type:"script",instance:null,count:0,state:null},r.set(n,l)),l):{type:"void",instance:null,count:0,state:null};default:throw Error(i(444,e))}}function Bo(e){return'href="'+Ln(e)+'"'}function Zi(e){return'link[rel="stylesheet"]['+e+"]"}function Rv(e){return p({},e,{"data-precedence":e.precedence,precedence:null})}function D4(e,n,r,l){e.querySelector('link[rel="preload"][as="style"]['+n+"]")?l.loading=1:(n=e.createElement("link"),l.preload=n,n.addEventListener("load",function(){return l.loading|=1}),n.addEventListener("error",function(){return l.loading|=2}),Jt(n,"link",r),vt(n),e.head.appendChild(n))}function $o(e){return'[src="'+Ln(e)+'"]'}function Ji(e){return"script[async]"+e}function Tv(e,n,r){if(n.count++,n.instance===null)switch(n.type){case"style":var l=e.querySelector('style[data-href~="'+Ln(r.href)+'"]');if(l)return n.instance=l,vt(l),l;var f=p({},r,{"data-href":r.href,"data-precedence":r.precedence,href:null,precedence:null});return l=(e.ownerDocument||e).createElement("style"),vt(l),Jt(l,"style",f),Is(l,r.precedence,e),n.instance=l;case"stylesheet":f=Bo(r.href);var h=e.querySelector(Zi(f));if(h)return n.state.loading|=4,n.instance=h,vt(h),h;l=Rv(r),(f=Hn.get(f))&&f2(l,f),h=(e.ownerDocument||e).createElement("link"),vt(h);var E=h;return E._p=new Promise(function(M,k){E.onload=M,E.onerror=k}),Jt(h,"link",l),n.state.loading|=4,Is(h,r.precedence,e),n.instance=h;case"script":return h=$o(r.src),(f=e.querySelector(Ji(h)))?(n.instance=f,vt(f),f):(l=r,(f=Hn.get(h))&&(l=p({},r),d2(l,f)),e=e.ownerDocument||e,f=e.createElement("script"),vt(f),Jt(f,"link",l),e.head.appendChild(f),n.instance=f);case"void":return null;default:throw Error(i(443,n.type))}else n.type==="stylesheet"&&(n.state.loading&4)===0&&(l=n.instance,n.state.loading|=4,Is(l,r.precedence,e));return n.instance}function Is(e,n,r){for(var l=r.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),f=l.length?l[l.length-1]:null,h=f,E=0;E<l.length;E++){var M=l[E];if(M.dataset.precedence===n)h=M;else if(h!==f)break}h?h.parentNode.insertBefore(e,h.nextSibling):(n=r.nodeType===9?r.head:r,n.insertBefore(e,n.firstChild))}function f2(e,n){e.crossOrigin==null&&(e.crossOrigin=n.crossOrigin),e.referrerPolicy==null&&(e.referrerPolicy=n.referrerPolicy),e.title==null&&(e.title=n.title)}function d2(e,n){e.crossOrigin==null&&(e.crossOrigin=n.crossOrigin),e.referrerPolicy==null&&(e.referrerPolicy=n.referrerPolicy),e.integrity==null&&(e.integrity=n.integrity)}var Hs=null;function Mv(e,n,r){if(Hs===null){var l=new Map,f=Hs=new Map;f.set(r,l)}else f=Hs,l=f.get(r),l||(l=new Map,f.set(r,l));if(l.has(e))return l;for(l.set(e,null),r=r.getElementsByTagName(e),f=0;f<r.length;f++){var h=r[f];if(!(h[Be]||h[Ce]||e==="link"&&h.getAttribute("rel")==="stylesheet")&&h.namespaceURI!=="http://www.w3.org/2000/svg"){var E=h.getAttribute(n)||"";E=e+E;var M=l.get(E);M?M.push(h):l.set(E,[h])}}return l}function Dv(e,n,r){e=e.ownerDocument||e,e.head.insertBefore(r,n==="title"?e.querySelector("head > title"):null)}function O4(e,n,r){if(r===1||n.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof n.precedence!="string"||typeof n.href!="string"||n.href==="")break;return!0;case"link":if(typeof n.rel!="string"||typeof n.href!="string"||n.href===""||n.onLoad||n.onError)break;return n.rel==="stylesheet"?(e=n.disabled,typeof n.precedence=="string"&&e==null):!0;case"script":if(n.async&&typeof n.async!="function"&&typeof n.async!="symbol"&&!n.onLoad&&!n.onError&&n.src&&typeof n.src=="string")return!0}return!1}function Ov(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function N4(e,n,r,l){if(r.type==="stylesheet"&&(typeof l.media!="string"||matchMedia(l.media).matches!==!1)&&(r.state.loading&4)===0){if(r.instance===null){var f=Bo(l.href),h=n.querySelector(Zi(f));if(h){n=h._p,n!==null&&typeof n=="object"&&typeof n.then=="function"&&(e.count++,e=Bs.bind(e),n.then(e,e)),r.state.loading|=4,r.instance=h,vt(h);return}h=n.ownerDocument||n,l=Rv(l),(f=Hn.get(f))&&f2(l,f),h=h.createElement("link"),vt(h);var E=h;E._p=new Promise(function(M,k){E.onload=M,E.onerror=k}),Jt(h,"link",l),r.instance=h}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(r,n),(n=r.state.preload)&&(r.state.loading&3)===0&&(e.count++,r=Bs.bind(e),n.addEventListener("load",r),n.addEventListener("error",r))}}var h2=0;function L4(e,n){return e.stylesheets&&e.count===0&&Vs(e,e.stylesheets),0<e.count||0<e.imgCount?function(r){var l=setTimeout(function(){if(e.stylesheets&&Vs(e,e.stylesheets),e.unsuspend){var h=e.unsuspend;e.unsuspend=null,h()}},6e4+n);0<e.imgBytes&&h2===0&&(h2=62500*h4());var f=setTimeout(function(){if(e.waitingForImages=!1,e.count===0&&(e.stylesheets&&Vs(e,e.stylesheets),e.unsuspend)){var h=e.unsuspend;e.unsuspend=null,h()}},(e.imgBytes>h2?50:800)+n);return e.unsuspend=r,function(){e.unsuspend=null,clearTimeout(l),clearTimeout(f)}}:null}function Bs(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Vs(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var $s=null;function Vs(e,n){e.stylesheets=null,e.unsuspend!==null&&(e.count++,$s=new Map,n.forEach(j4,e),$s=null,Bs.call(e))}function j4(e,n){if(!(n.state.loading&4)){var r=$s.get(e);if(r)var l=r.get(null);else{r=new Map,$s.set(e,r);for(var f=e.querySelectorAll("link[data-precedence],style[data-precedence]"),h=0;h<f.length;h++){var E=f[h];(E.nodeName==="LINK"||E.getAttribute("media")!=="not all")&&(r.set(E.dataset.precedence,E),l=E)}l&&r.set(null,l)}f=n.instance,E=f.getAttribute("data-precedence"),h=r.get(E)||l,h===l&&r.set(null,f),r.set(E,f),this.count++,l=Bs.bind(this),f.addEventListener("load",l),f.addEventListener("error",l),h?h.parentNode.insertBefore(f,h.nextSibling):(e=e.nodeType===9?e.head:e,e.insertBefore(f,e.firstChild)),n.state.loading|=4}}var Wi={$$typeof:R,Provider:null,Consumer:null,_currentValue:K,_currentValue2:K,_threadCount:0};function F4(e,n,r,l,f,h,E,M,k){this.tag=1,this.containerInfo=e,this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.next=this.pendingContext=this.context=this.cancelPendingCommit=null,this.callbackPriority=0,this.expirationTimes=Qa(-1),this.entangledLanes=this.shellSuspendCounter=this.errorRecoveryDisabledLanes=this.expiredLanes=this.warmLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=Qa(0),this.hiddenUpdates=Qa(null),this.identifierPrefix=l,this.onUncaughtError=f,this.onCaughtError=h,this.onRecoverableError=E,this.pooledCache=null,this.pooledCacheLanes=0,this.formState=k,this.incompleteTransitions=new Map}function Nv(e,n,r,l,f,h,E,M,k,Q,ae,le){return e=new F4(e,n,r,E,k,Q,ae,le,M),n=1,h===!0&&(n|=24),h=Cn(3,null,null,n),e.current=h,h.stateNode=e,n=Gc(),n.refCount++,e.pooledCache=n,n.refCount++,h.memoizedState={element:l,isDehydrated:r,cache:n},Xc(h),e}function Lv(e){return e?(e=Co,e):Co}function jv(e,n,r,l,f,h){f=Lv(f),l.context===null?l.context=f:l.pendingContext=f,l=nr(n),l.payload={element:r},h=h===void 0?null:h,h!==null&&(l.callback=h),r=ar(e,l,n),r!==null&&(vn(r,e,n),Oi(r,e,n))}function Fv(e,n){if(e=e.memoizedState,e!==null&&e.dehydrated!==null){var r=e.retryLane;e.retryLane=r!==0&&r<n?r:n}}function p2(e,n){Fv(e,n),(e=e.alternate)&&Fv(e,n)}function kv(e){if(e.tag===13||e.tag===31){var n=Fr(e,67108864);n!==null&&vn(n,e,67108864),p2(e,67108864)}}function zv(e){if(e.tag===13||e.tag===31){var n=wn();n=B(n);var r=Fr(e,n);r!==null&&vn(r,e,n),p2(e,n)}}var qs=!0;function k4(e,n,r,l){var f=U.T;U.T=null;var h=H.p;try{H.p=2,m2(e,n,r,l)}finally{H.p=h,U.T=f}}function z4(e,n,r,l){var f=U.T;U.T=null;var h=H.p;try{H.p=8,m2(e,n,r,l)}finally{H.p=h,U.T=f}}function m2(e,n,r,l){if(qs){var f=v2(l);if(f===null)t2(e,n,l,Gs,r),Pv(e,l);else if(P4(f,e,n,r,l))l.stopPropagation();else if(Pv(e,l),n&4&&-1<U4.indexOf(e)){for(;f!==null;){var h=Rt(f);if(h!==null)switch(h.tag){case 3:if(h=h.stateNode,h.current.memoizedState.isDehydrated){var E=Xn(h.pendingLanes);if(E!==0){var M=h;for(M.pendingLanes|=2,M.entangledLanes|=2;E;){var k=1<<31-tn(E);M.entanglements[1]|=k,E&=~k}pa(h),(nt&6)===0&&(Ts=kt()+500,Yi(0))}}break;case 31:case 13:M=Fr(h,2),M!==null&&vn(M,h,2),Ds(),p2(h,2)}if(h=v2(l),h===null&&t2(e,n,l,Gs,r),h===f)break;f=h}f!==null&&l.stopPropagation()}else t2(e,n,l,null,r)}}function v2(e){return e=yc(e),g2(e)}var Gs=null;function g2(e){if(Gs=null,e=Ct(e),e!==null){var n=u(e);if(n===null)e=null;else{var r=n.tag;if(r===13){if(e=c(n),e!==null)return e;e=null}else if(r===31){if(e=d(n),e!==null)return e;e=null}else if(r===3){if(n.stateNode.current.memoizedState.isDehydrated)return n.tag===3?n.stateNode.containerInfo:null;e=null}else n!==e&&(e=null)}}return Gs=e,null}function Uv(e){switch(e){case"beforetoggle":case"cancel":case"click":case"close":case"contextmenu":case"copy":case"cut":case"auxclick":case"dblclick":case"dragend":case"dragstart":case"drop":case"focusin":case"focusout":case"input":case"invalid":case"keydown":case"keypress":case"keyup":case"mousedown":case"mouseup":case"paste":case"pause":case"play":case"pointercancel":case"pointerdown":case"pointerup":case"ratechange":case"reset":case"resize":case"seeked":case"submit":case"toggle":case"touchcancel":case"touchend":case"touchstart":case"volumechange":case"change":case"selectionchange":case"textInput":case"compositionstart":case"compositionend":case"compositionupdate":case"beforeblur":case"afterblur":case"beforeinput":case"blur":case"fullscreenchange":case"focus":case"hashchange":case"popstate":case"select":case"selectstart":return 2;case"drag":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"mousemove":case"mouseout":case"mouseover":case"pointermove":case"pointerout":case"pointerover":case"scroll":case"touchmove":case"wheel":case"mouseenter":case"mouseleave":case"pointerenter":case"pointerleave":return 8;case"message":switch(Kn()){case ye:return 2;case at:return 8;case ve:case je:return 32;case He:return 268435456;default:return 32}default:return 32}}var y2=!1,pr=null,mr=null,vr=null,el=new Map,tl=new Map,gr=[],U4="mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset".split(" ");function Pv(e,n){switch(e){case"focusin":case"focusout":pr=null;break;case"dragenter":case"dragleave":mr=null;break;case"mouseover":case"mouseout":vr=null;break;case"pointerover":case"pointerout":el.delete(n.pointerId);break;case"gotpointercapture":case"lostpointercapture":tl.delete(n.pointerId)}}function nl(e,n,r,l,f,h){return e===null||e.nativeEvent!==h?(e={blockedOn:n,domEventName:r,eventSystemFlags:l,nativeEvent:h,targetContainers:[f]},n!==null&&(n=Rt(n),n!==null&&kv(n)),e):(e.eventSystemFlags|=l,n=e.targetContainers,f!==null&&n.indexOf(f)===-1&&n.push(f),e)}function P4(e,n,r,l,f){switch(n){case"focusin":return pr=nl(pr,e,n,r,l,f),!0;case"dragenter":return mr=nl(mr,e,n,r,l,f),!0;case"mouseover":return vr=nl(vr,e,n,r,l,f),!0;case"pointerover":var h=f.pointerId;return el.set(h,nl(el.get(h)||null,e,n,r,l,f)),!0;case"gotpointercapture":return h=f.pointerId,tl.set(h,nl(tl.get(h)||null,e,n,r,l,f)),!0}return!1}function Iv(e){var n=Ct(e.target);if(n!==null){var r=u(n);if(r!==null){if(n=r.tag,n===13){if(n=c(r),n!==null){e.blockedOn=n,ge(e.priority,function(){zv(r)});return}}else if(n===31){if(n=d(r),n!==null){e.blockedOn=n,ge(e.priority,function(){zv(r)});return}}else if(n===3&&r.stateNode.current.memoizedState.isDehydrated){e.blockedOn=r.tag===3?r.stateNode.containerInfo:null;return}}}e.blockedOn=null}function Ys(e){if(e.blockedOn!==null)return!1;for(var n=e.targetContainers;0<n.length;){var r=v2(e.nativeEvent);if(r===null){r=e.nativeEvent;var l=new r.constructor(r.type,r);gc=l,r.target.dispatchEvent(l),gc=null}else return n=Rt(r),n!==null&&kv(n),e.blockedOn=r,!1;n.shift()}return!0}function Hv(e,n,r){Ys(e)&&r.delete(n)}function I4(){y2=!1,pr!==null&&Ys(pr)&&(pr=null),mr!==null&&Ys(mr)&&(mr=null),vr!==null&&Ys(vr)&&(vr=null),el.forEach(Hv),tl.forEach(Hv)}function Qs(e,n){e.blockedOn===n&&(e.blockedOn=null,y2||(y2=!0,t.unstable_scheduleCallback(t.unstable_NormalPriority,I4)))}var Ks=null;function Bv(e){Ks!==e&&(Ks=e,t.unstable_scheduleCallback(t.unstable_NormalPriority,function(){Ks===e&&(Ks=null);for(var n=0;n<e.length;n+=3){var r=e[n],l=e[n+1],f=e[n+2];if(typeof l!="function"){if(g2(l||r)===null)continue;break}var h=Rt(r);h!==null&&(e.splice(n,3),n-=3,v0(h,{pending:!0,data:f,method:r.method,action:l},l,f))}}))}function Vo(e){function n(k){return Qs(k,e)}pr!==null&&Qs(pr,e),mr!==null&&Qs(mr,e),vr!==null&&Qs(vr,e),el.forEach(n),tl.forEach(n);for(var r=0;r<gr.length;r++){var l=gr[r];l.blockedOn===e&&(l.blockedOn=null)}for(;0<gr.length&&(r=gr[0],r.blockedOn===null);)Iv(r),r.blockedOn===null&&gr.shift();if(r=(e.ownerDocument||e).$$reactFormReplay,r!=null)for(l=0;l<r.length;l+=3){var f=r[l],h=r[l+1],E=f[be]||null;if(typeof h=="function")E||Bv(r);else if(E){var M=null;if(h&&h.hasAttribute("formAction")){if(f=h,E=h[be]||null)M=E.formAction;else if(g2(f)!==null)continue}else M=E.action;typeof M=="function"?r[l+1]=M:(r.splice(l,3),l-=3),Bv(r)}}}function $v(){function e(h){h.canIntercept&&h.info==="react-transition"&&h.intercept({handler:function(){return new Promise(function(E){return f=E})},focusReset:"manual",scroll:"manual"})}function n(){f!==null&&(f(),f=null),l||setTimeout(r,20)}function r(){if(!l&&!navigation.transition){var h=navigation.currentEntry;h&&h.url!=null&&navigation.navigate(h.url,{state:h.getState(),info:"react-transition",history:"replace"})}}if(typeof navigation=="object"){var l=!1,f=null;return navigation.addEventListener("navigate",e),navigation.addEventListener("navigatesuccess",n),navigation.addEventListener("navigateerror",n),setTimeout(r,100),function(){l=!0,navigation.removeEventListener("navigate",e),navigation.removeEventListener("navigatesuccess",n),navigation.removeEventListener("navigateerror",n),f!==null&&(f(),f=null)}}}function A2(e){this._internalRoot=e}Xs.prototype.render=A2.prototype.render=function(e){var n=this._internalRoot;if(n===null)throw Error(i(409));var r=n.current,l=wn();jv(r,l,e,n,null,null)},Xs.prototype.unmount=A2.prototype.unmount=function(){var e=this._internalRoot;if(e!==null){this._internalRoot=null;var n=e.containerInfo;jv(e.current,2,null,e,null,null),Ds(),n[Te]=null}};function Xs(e){this._internalRoot=e}Xs.prototype.unstable_scheduleHydration=function(e){if(e){var n=he();e={blockedOn:null,target:e,priority:n};for(var r=0;r<gr.length&&n!==0&&n<gr[r].priority;r++);gr.splice(r,0,e),r===0&&Iv(e)}};var Vv=a.version;if(Vv!=="19.2.4")throw Error(i(527,Vv,"19.2.4"));H.findDOMNode=function(e){var n=e._reactInternals;if(n===void 0)throw typeof e.render=="function"?Error(i(188)):(e=Object.keys(e).join(","),Error(i(268,e)));return e=m(n),e=e!==null?A(e):null,e=e===null?null:e.stateNode,e};var H4={bundleType:0,version:"19.2.4",rendererPackageName:"react-dom",currentDispatcherRef:U,reconcilerVersion:"19.2.4"};if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"){var Zs=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!Zs.isDisabled&&Zs.supportsFiber)try{zt=Zs.inject(H4),mt=Zs}catch{}}return rl.createRoot=function(e,n){if(!s(e))throw Error(i(299));var r=!1,l="",f=Zp,h=Jp,E=Wp;return n!=null&&(n.unstable_strictMode===!0&&(r=!0),n.identifierPrefix!==void 0&&(l=n.identifierPrefix),n.onUncaughtError!==void 0&&(f=n.onUncaughtError),n.onCaughtError!==void 0&&(h=n.onCaughtError),n.onRecoverableError!==void 0&&(E=n.onRecoverableError)),n=Nv(e,1,!1,null,null,r,l,null,f,h,E,$v),e[Te]=n.current,e2(e),new A2(n)},rl.hydrateRoot=function(e,n,r){if(!s(e))throw Error(i(299));var l=!1,f="",h=Zp,E=Jp,M=Wp,k=null;return r!=null&&(r.unstable_strictMode===!0&&(l=!0),r.identifierPrefix!==void 0&&(f=r.identifierPrefix),r.onUncaughtError!==void 0&&(h=r.onUncaughtError),r.onCaughtError!==void 0&&(E=r.onCaughtError),r.onRecoverableError!==void 0&&(M=r.onRecoverableError),r.formState!==void 0&&(k=r.formState)),n=Nv(e,1,!0,n,r??null,l,f,k,h,E,M,$v),n.context=Lv(null),r=n.current,l=wn(),l=B(l),f=nr(l),f.callback=null,ar(r,f,l),r=l,n.current.lanes=r,sa(n,r),pa(n),e[Te]=n.current,e2(e),new Xs(n)},rl.version="19.2.4",rl}var tg;function Eb(){if(tg)return S2.exports;tg=1;function t(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(a){console.error(a)}}return t(),S2.exports=bb(),S2.exports}var Sb=Eb();var oy=t=>{throw TypeError(t)},xb=(t,a,o)=>a.has(t)||oy("Cannot "+o),R2=(t,a,o)=>(xb(t,a,"read from private field"),o?o.call(t):a.get(t)),wb=(t,a,o)=>a.has(t)?oy("Cannot add the same private member more than once"):a instanceof WeakSet?a.add(t):a.set(t,o),ng="popstate";function ag(t){return typeof t=="object"&&t!=null&&"pathname"in t&&"search"in t&&"hash"in t&&"state"in t&&"key"in t}function _b(t={}){function a(i,s){let u=s.state?.masked,{pathname:c,search:d,hash:v}=u||i.location;return vl("",{pathname:c,search:d,hash:v},s.state&&s.state.usr||null,s.state&&s.state.key||"default",u?{pathname:i.location.pathname,search:i.location.search,hash:i.location.hash}:void 0)}function o(i,s){return typeof s=="string"?s:ya(s)}return Tb(a,o,null,t)}function Ie(t,a){if(t===!1||t===null||typeof t>"u")throw new Error(a)}function Dt(t,a){if(!t){typeof console<"u"&&console.warn(a);try{throw new Error(a)}catch{}}}function Rb(){return Math.random().toString(36).substring(2,10)}function rg(t,a){return{usr:t.state,key:t.key,idx:a,masked:t.unstable_mask?{pathname:t.pathname,search:t.search,hash:t.hash}:void 0}}function vl(t,a,o=null,i,s){return{pathname:typeof t=="string"?t:t.pathname,search:"",hash:"",...typeof a=="string"?Aa(a):a,state:o,key:a&&a.key||i||Rb(),unstable_mask:s}}function ya({pathname:t="/",search:a="",hash:o=""}){return a&&a!=="?"&&(t+=a.charAt(0)==="?"?a:"?"+a),o&&o!=="#"&&(t+=o.charAt(0)==="#"?o:"#"+o),t}function Aa(t){let a={};if(t){let o=t.indexOf("#");o>=0&&(a.hash=t.substring(o),t=t.substring(0,o));let i=t.indexOf("?");i>=0&&(a.search=t.substring(i),t=t.substring(0,i)),t&&(a.pathname=t)}return a}function Tb(t,a,o,i={}){let{window:s=document.defaultView,v5Compat:u=!1}=i,c=s.history,d="POP",v=null,m=A();m==null&&(m=0,c.replaceState({...c.state,idx:m},""));function A(){return(c.state||{idx:null}).idx}function p(){d="POP";let w=A(),D=w==null?null:w-m;m=w,v&&v({action:d,location:x.location,delta:D})}function C(w,D){d="PUSH";let T=ag(w)?w:vl(x.location,w,D);m=A()+1;let R=rg(T,m),_=x.createHref(T.unstable_mask||T);try{c.pushState(R,"",_)}catch(N){if(N instanceof DOMException&&N.name==="DataCloneError")throw N;s.location.assign(_)}u&&v&&v({action:d,location:x.location,delta:1})}function b(w,D){d="REPLACE";let T=ag(w)?w:vl(x.location,w,D);m=A();let R=rg(T,m),_=x.createHref(T.unstable_mask||T);c.replaceState(R,"",_),u&&v&&v({action:d,location:x.location,delta:0})}function S(w){return iy(w)}let x={get action(){return d},get location(){return t(s,c)},listen(w){if(v)throw new Error("A history only accepts one active listener");return s.addEventListener(ng,p),v=w,()=>{s.removeEventListener(ng,p),v=null}},createHref(w){return a(s,w)},createURL:S,encodeLocation(w){let D=S(w);return{pathname:D.pathname,search:D.search,hash:D.hash}},push:C,replace:b,go(w){return c.go(w)}};return x}function iy(t,a=!1){let o="http://localhost";typeof window<"u"&&(o=window.location.origin!=="null"?window.location.origin:window.location.href),Ie(o,"No window.location.(origin|href) available to create URL");let i=typeof t=="string"?t:ya(t);return i=i.replace(/ $/,"%20"),!a&&i.startsWith("//")&&(i=o+i),new URL(i,o)}var sl,og=class{constructor(t){if(wb(this,sl,new Map),t)for(let[a,o]of t)this.set(a,o)}get(t){if(R2(this,sl).has(t))return R2(this,sl).get(t);if(t.defaultValue!==void 0)return t.defaultValue;throw new Error("No value found for context")}set(t,a){R2(this,sl).set(t,a)}};sl=new WeakMap;var Mb=new Set(["lazy","caseSensitive","path","id","index","children"]);function Db(t){return Mb.has(t)}var Ob=new Set(["lazy","caseSensitive","path","id","index","middleware","children"]);function Nb(t){return Ob.has(t)}function Lb(t){return t.index===!0}function gl(t,a,o=[],i={},s=!1){return t.map((u,c)=>{let d=[...o,String(c)],v=typeof u.id=="string"?u.id:d.join("-");if(Ie(u.index!==!0||!u.children,"Cannot specify children on an index route"),Ie(s||!i[v],`Found a route id collision on id "${v}". Route id's must be globally unique within Data Router usages`),Lb(u)){let m={...u,id:v};return i[v]=ig(m,a(m)),m}else{let m={...u,id:v,children:void 0};return i[v]=ig(m,a(m)),u.children&&(m.children=gl(u.children,a,d,i,s)),m}})}function ig(t,a){return Object.assign(t,{...a,...typeof a.lazy=="object"&&a.lazy!=null?{lazy:{...t.lazy,...a.lazy}}:{}})}function Ha(t,a,o="/"){return ul(t,a,o,!1)}function ul(t,a,o,i){let s=typeof a=="string"?Aa(a):a,u=Dn(s.pathname||"/",o);if(u==null)return null;let c=sy(t);jb(c);let d=null;for(let v=0;d==null&&v<c.length;++v){let m=cy(u);d=$b(c[v],m,i)}return d}function ly(t,a){let{route:o,pathname:i,params:s}=t;return{id:o.id,pathname:i,params:s,data:a[o.id],loaderData:a[o.id],handle:o.handle}}function sy(t,a=[],o=[],i="",s=!1){let u=(c,d,v=s,m)=>{let A={relativePath:m===void 0?c.path||"":m,caseSensitive:c.caseSensitive===!0,childrenIndex:d,route:c};if(A.relativePath.startsWith("/")){if(!A.relativePath.startsWith(i)&&v)return;Ie(A.relativePath.startsWith(i),`Absolute route path "${A.relativePath}" nested under path "${i}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),A.relativePath=A.relativePath.slice(i.length)}let p=na([i,A.relativePath]),C=o.concat(A);c.children&&c.children.length>0&&(Ie(c.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${p}".`),sy(c.children,a,C,p,v)),!(c.path==null&&!c.index)&&a.push({path:p,score:Hb(p,c.index),routesMeta:C})};return t.forEach((c,d)=>{if(c.path===""||!c.path?.includes("?"))u(c,d);else for(let v of uy(c.path))u(c,d,!0,v)}),a}function uy(t){let a=t.split("/");if(a.length===0)return[];let[o,...i]=a,s=o.endsWith("?"),u=o.replace(/\?$/,"");if(i.length===0)return s?[u,""]:[u];let c=uy(i.join("/")),d=[];return d.push(...c.map(v=>v===""?u:[u,v].join("/"))),s&&d.push(...c),d.map(v=>t.startsWith("/")&&v===""?"/":v)}function jb(t){t.sort((a,o)=>a.score!==o.score?o.score-a.score:Bb(a.routesMeta.map(i=>i.childrenIndex),o.routesMeta.map(i=>i.childrenIndex)))}var Fb=/^:[\w-]+$/,kb=3,zb=2,Ub=1,Pb=10,Ib=-2,lg=t=>t==="*";function Hb(t,a){let o=t.split("/"),i=o.length;return o.some(lg)&&(i+=Ib),a&&(i+=zb),o.filter(s=>!lg(s)).reduce((s,u)=>s+(Fb.test(u)?kb:u===""?Ub:Pb),i)}function Bb(t,a){return t.length===a.length&&t.slice(0,-1).every((i,s)=>i===a[s])?t[t.length-1]-a[a.length-1]:0}function $b(t,a,o=!1){let{routesMeta:i}=t,s={},u="/",c=[];for(let d=0;d<i.length;++d){let v=i[d],m=d===i.length-1,A=u==="/"?a:a.slice(u.length)||"/",p=Zr({path:v.relativePath,caseSensitive:v.caseSensitive,end:m},A),C=v.route;if(!p&&m&&o&&!i[i.length-1].route.index&&(p=Zr({path:v.relativePath,caseSensitive:v.caseSensitive,end:!1},A)),!p)return null;Object.assign(s,p.params),c.push({params:s,pathname:na([u,p.pathname]),pathnameBase:Yb(na([u,p.pathnameBase])),route:C}),p.pathnameBase!=="/"&&(u=na([u,p.pathnameBase]))}return c}function Zr(t,a){typeof t=="string"&&(t={path:t,caseSensitive:!1,end:!0});let[o,i]=Vb(t.path,t.caseSensitive,t.end),s=a.match(o);if(!s)return null;let u=s[0],c=u.replace(/(.)\/+$/,"$1"),d=s.slice(1);return{params:i.reduce((m,{paramName:A,isOptional:p},C)=>{if(A==="*"){let S=d[C]||"";c=u.slice(0,u.length-S.length).replace(/(.)\/+$/,"$1")}const b=d[C];return p&&!b?m[A]=void 0:m[A]=(b||"").replace(/%2F/g,"/"),m},{}),pathname:u,pathnameBase:c,pattern:t}}function Vb(t,a=!1,o=!0){Dt(t==="*"||!t.endsWith("*")||t.endsWith("/*"),`Route path "${t}" will be treated as if it were "${t.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${t.replace(/\*$/,"/*")}".`);let i=[],s="^"+t.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(c,d,v,m,A)=>{if(i.push({paramName:d,isOptional:v!=null}),v){let p=A.charAt(m+c.length);return p&&p!=="/"?"/([^\\/]*)":"(?:/([^\\/]*))?"}return"/([^\\/]+)"}).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return t.endsWith("*")?(i.push({paramName:"*"}),s+=t==="*"||t==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):o?s+="\\/*$":t!==""&&t!=="/"&&(s+="(?:(?=\\/|$))"),[new RegExp(s,a?void 0:"i"),i]}function cy(t){try{return t.split("/").map(a=>decodeURIComponent(a).replace(/\//g,"%2F")).join("/")}catch(a){return Dt(!1,`The URL path "${t}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${a}).`),t}}function Dn(t,a){if(a==="/")return t;if(!t.toLowerCase().startsWith(a.toLowerCase()))return null;let o=a.endsWith("/")?a.length-1:a.length,i=t.charAt(o);return i&&i!=="/"?null:t.slice(o)||"/"}function qb({basename:t,pathname:a}){return a==="/"?t:na([t,a])}var fy=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,ed=t=>fy.test(t);function Gb(t,a="/"){let{pathname:o,search:i="",hash:s=""}=typeof t=="string"?Aa(t):t,u;return o?(o=o.replace(/\/\/+/g,"/"),o.startsWith("/")?u=sg(o.substring(1),"/"):u=sg(o,a)):u=a,{pathname:u,search:Qb(i),hash:Kb(s)}}function sg(t,a){let o=a.replace(/\/+$/,"").split("/");return t.split("/").forEach(s=>{s===".."?o.length>1&&o.pop():s!=="."&&o.push(s)}),o.length>1?o.join("/"):"/"}function T2(t,a,o,i){return`Cannot include a '${t}' character in a manually specified \`to.${a}\` field [${JSON.stringify(i)}]. Please separate it out to the \`to.${o}\` field. Alternatively you may provide the full path as a string in <Link to="..."> and the router will parse it for you.`}function dy(t){return t.filter((a,o)=>o===0||a.route.path&&a.route.path.length>0)}function td(t){let a=dy(t);return a.map((o,i)=>i===a.length-1?o.pathname:o.pathnameBase)}function Pu(t,a,o,i=!1){let s;typeof t=="string"?s=Aa(t):(s={...t},Ie(!s.pathname||!s.pathname.includes("?"),T2("?","pathname","search",s)),Ie(!s.pathname||!s.pathname.includes("#"),T2("#","pathname","hash",s)),Ie(!s.search||!s.search.includes("#"),T2("#","search","hash",s)));let u=t===""||s.pathname==="",c=u?"/":s.pathname,d;if(c==null)d=o;else{let p=a.length-1;if(!i&&c.startsWith("..")){let C=c.split("/");for(;C[0]==="..";)C.shift(),p-=1;s.pathname=C.join("/")}d=p>=0?a[p]:"/"}let v=Gb(s,d),m=c&&c!=="/"&&c.endsWith("/"),A=(u||c===".")&&o.endsWith("/");return!v.pathname.endsWith("/")&&(m||A)&&(v.pathname+="/"),v}var na=t=>t.join("/").replace(/\/\/+/g,"/"),Yb=t=>t.replace(/\/+$/,"").replace(/^\/*/,"/"),Qb=t=>!t||t==="?"?"":t.startsWith("?")?t:"?"+t,Kb=t=>!t||t==="#"?"":t.startsWith("#")?t:"#"+t,xl=class{constructor(t,a,o,i=!1){this.status=t,this.statusText=a||"",this.internal=i,o instanceof Error?(this.data=o.toString(),this.error=o):this.data=o}};function yl(t){return t!=null&&typeof t.status=="number"&&typeof t.statusText=="string"&&typeof t.internal=="boolean"&&"data"in t}function wl(t){return t.map(a=>a.route.path).filter(Boolean).join("/").replace(/\/\/*/g,"/")||"/"}var hy=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function py(t,a){let o=t;if(typeof o!="string"||!fy.test(o))return{absoluteURL:void 0,isExternal:!1,to:o};let i=o,s=!1;if(hy)try{let u=new URL(window.location.href),c=o.startsWith("//")?new URL(u.protocol+o):new URL(o),d=Dn(c.pathname,a);c.origin===u.origin&&d!=null?o=d+c.search+c.hash:s=!0}catch{Dt(!1,`<Link to="${o}"> contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:i,isExternal:s,to:o}}var br=Symbol("Uninstrumented");function Xb(t,a){let o={lazy:[],"lazy.loader":[],"lazy.action":[],"lazy.middleware":[],middleware:[],loader:[],action:[]};t.forEach(s=>s({id:a.id,index:a.index,path:a.path,instrument(u){let c=Object.keys(o);for(let d of c)u[d]&&o[d].push(u[d])}}));let i={};if(typeof a.lazy=="function"&&o.lazy.length>0){let s=Xo(o.lazy,a.lazy,()=>{});s&&(i.lazy=s)}if(typeof a.lazy=="object"){let s=a.lazy;["middleware","loader","action"].forEach(u=>{let c=s[u],d=o[`lazy.${u}`];if(typeof c=="function"&&d.length>0){let v=Xo(d,c,()=>{});v&&(i.lazy=Object.assign(i.lazy||{},{[u]:v}))}})}return["loader","action"].forEach(s=>{let u=a[s];if(typeof u=="function"&&o[s].length>0){let c=u[br]??u,d=Xo(o[s],c,(...v)=>ug(v[0]));d&&(s==="loader"&&c.hydrate===!0&&(d.hydrate=!0),d[br]=c,i[s]=d)}}),a.middleware&&a.middleware.length>0&&o.middleware.length>0&&(i.middleware=a.middleware.map(s=>{let u=s[br]??s,c=Xo(o.middleware,u,(...d)=>ug(d[0]));return c?(c[br]=u,c):s})),i}function Zb(t,a){let o={navigate:[],fetch:[]};if(a.forEach(i=>i({instrument(s){let u=Object.keys(s);for(let c of u)s[c]&&o[c].push(s[c])}})),o.navigate.length>0){let i=t.navigate[br]??t.navigate,s=Xo(o.navigate,i,(...u)=>{let[c,d]=u;return{to:typeof c=="number"||typeof c=="string"?c:c?ya(c):".",...cg(t,d??{})}});s&&(s[br]=i,t.navigate=s)}if(o.fetch.length>0){let i=t.fetch[br]??t.fetch,s=Xo(o.fetch,i,(...u)=>{let[c,,d,v]=u;return{href:d??".",fetcherKey:c,...cg(t,v??{})}});s&&(s[br]=i,t.fetch=s)}return t}function Xo(t,a,o){return t.length===0?null:async(...i)=>{let s=await my(t,o(...i),()=>a(...i),t.length-1);if(s.type==="error")throw s.value;return s.value}}async function my(t,a,o,i){let s=t[i],u;if(s){let c,d=async()=>(c?console.error("You cannot call instrumented handlers more than once"):c=my(t,a,o,i-1),u=await c,Ie(u,"Expected a result"),u.type==="error"&&u.value instanceof Error?{status:"error",error:u.value}:{status:"success",error:void 0});try{await s(d,a)}catch(v){console.error("An instrumentation function threw an error:",v)}c||await d(),await c}else try{u={type:"success",value:await o()}}catch(c){u={type:"error",value:c}}return u||{type:"error",value:new Error("No result assigned in instrumentation chain.")}}function ug(t){let{request:a,context:o,params:i,unstable_pattern:s}=t;return{request:Jb(a),params:{...i},unstable_pattern:s,context:Wb(o)}}function cg(t,a){return{currentUrl:ya(t.state.location),..."formMethod"in a?{formMethod:a.formMethod}:{},..."formEncType"in a?{formEncType:a.formEncType}:{},..."formData"in a?{formData:a.formData}:{},..."body"in a?{body:a.body}:{}}}function Jb(t){return{method:t.method,url:t.url,headers:{get:(...a)=>t.headers.get(...a)}}}function Wb(t){if(tE(t)){let a={...t};return Object.freeze(a),a}else return{get:a=>t.get(a)}}var eE=Object.getOwnPropertyNames(Object.prototype).sort().join("\0");function tE(t){if(t===null||typeof t!="object")return!1;const a=Object.getPrototypeOf(t);return a===Object.prototype||a===null||Object.getOwnPropertyNames(a).sort().join("\0")===eE}var vy=["POST","PUT","PATCH","DELETE"],nE=new Set(vy),aE=["GET",...vy],rE=new Set(aE),gy=new Set([301,302,303,307,308]),oE=new Set([307,308]),M2={state:"idle",location:void 0,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0},iE={state:"idle",data:void 0,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0},ol={state:"unblocked",proceed:void 0,reset:void 0,location:void 0},lE=t=>({hasErrorBoundary:!!t.hasErrorBoundary}),yy="remix-router-transitions",Ay=Symbol("ResetLoaderData");function sE(t){const a=t.window?t.window:typeof window<"u"?window:void 0,o=typeof a<"u"&&typeof a.document<"u"&&typeof a.document.createElement<"u";Ie(t.routes.length>0,"You must provide a non-empty routes array to createRouter");let i=t.hydrationRouteProperties||[],s=t.mapRouteProperties||lE,u=s;if(t.unstable_instrumentations){let z=t.unstable_instrumentations;u=B=>({...s(B),...Xb(z.map(X=>X.route).filter(Boolean),B)})}let c={},d=gl(t.routes,u,void 0,c),v,m=t.basename||"/";m.startsWith("/")||(m=`/${m}`);let A=t.dataStrategy||hE,p={unstable_passThroughRequests:!1,...t.future},C=null,b=new Set,S=null,x=null,w=null,D=t.hydrationData!=null,T=Ha(d,t.history.location,m),R=!1,_=null,N,j;if(T==null&&!t.patchRoutesOnNavigation){let z=Bn(404,{pathname:t.history.location.pathname}),{matches:B,route:X}=Js(d);N=!0,j=!N,T=B,_={[X.id]:z}}else if(T&&!t.hydrationData&&Qa(T,d,t.history.location.pathname).active&&(T=null),T)if(T.some(z=>z.route.lazy))N=!1,j=!N;else if(!T.some(z=>nd(z.route)))N=!0,j=!N;else{let z=t.hydrationData?t.hydrationData.loaderData:null,B=t.hydrationData?t.hydrationData.errors:null,X=T;if(B){let he=T.findIndex(ge=>B[ge.route.id]!==void 0);X=X.slice(0,he+1)}j=!1,N=!0,X.forEach(he=>{let ge=Cy(he.route,z,B);j=j||ge.renderFallback,N=N&&!ge.shouldLoad})}else{N=!1,j=!N,T=[];let z=Qa(null,d,t.history.location.pathname);z.active&&z.matches&&(R=!0,T=z.matches)}let F,O={historyAction:t.history.action,location:t.history.location,matches:T,initialized:N,renderFallback:j,navigation:M2,restoreScrollPosition:t.hydrationData!=null?!1:null,preventScrollReset:!1,revalidation:"idle",loaderData:t.hydrationData&&t.hydrationData.loaderData||{},actionData:t.hydrationData&&t.hydrationData.actionData||null,errors:t.hydrationData&&t.hydrationData.errors||_,fetchers:new Map,blockers:new Map},I="POP",re=null,pe=!1,ce,de=!1,J=new Map,fe=null,U=!1,H=!1,K=new Set,G=new Map,se=0,L=-1,$=new Map,ne=new Set,ie=new Map,Ae=new Map,Se=new Set,ue=new Map,q,we=null;function lt(){if(C=t.history.listen(({action:z,location:B,delta:X})=>{if(q){q(),q=void 0;return}Dt(ue.size===0||X!=null,"You are trying to use a blocker on a POP navigation to a location that was not created by @remix-run/router. This will fail silently in production. This can happen if you are navigating outside the router via `window.history.pushState`/`window.location.hash` instead of using router navigation APIs. This can also happen if you are using createHashRouter and the user manually changes the URL.");let he=Mr({currentLocation:O.location,nextLocation:B,historyAction:z});if(he&&X!=null){let ge=new Promise(_e=>{q=_e});t.history.go(X*-1),Ea(he,{state:"blocked",location:B,proceed(){Ea(he,{state:"proceeding",proceed:void 0,reset:void 0,location:B}),ge.then(()=>t.history.go(X))},reset(){let _e=new Map(O.blockers);_e.set(he,ol),te({blockers:_e})}}),re?.resolve(),re=null;return}return Je(z,B)}),o){OE(a,J);let z=()=>NE(a,J);a.addEventListener("pagehide",z),fe=()=>a.removeEventListener("pagehide",z)}return O.initialized||Je("POP",O.location,{initialHydration:!0}),F}function Xe(){C&&C(),fe&&fe(),b.clear(),ce&&ce.abort(),O.fetchers.forEach((z,B)=>zt(B)),O.blockers.forEach((z,B)=>Tr(B))}function W(z){return b.add(z),()=>b.delete(z)}function te(z,B={}){z.matches&&(z.matches=z.matches.map(ge=>{let _e=c[ge.route.id],Ce=ge.route;return Ce.element!==_e.element||Ce.errorElement!==_e.errorElement||Ce.hydrateFallbackElement!==_e.hydrateFallbackElement?{...ge,route:_e}:ge})),O={...O,...z};let X=[],he=[];O.fetchers.forEach((ge,_e)=>{ge.state==="idle"&&(Se.has(_e)?X.push(_e):he.push(_e))}),Se.forEach(ge=>{!O.fetchers.has(ge)&&!G.has(ge)&&X.push(ge)}),[...b].forEach(ge=>ge(O,{deletedFetchers:X,newErrors:z.errors??null,viewTransitionOpts:B.viewTransitionOpts,flushSync:B.flushSync===!0})),X.forEach(ge=>zt(ge)),he.forEach(ge=>O.fetchers.delete(ge))}function pt(z,B,{flushSync:X}={}){let he=O.actionData!=null&&O.navigation.formMethod!=null&&rn(O.navigation.formMethod)&&O.navigation.state==="loading"&&z.state?._isRedirect!==!0,ge;B.actionData?Object.keys(B.actionData).length>0?ge=B.actionData:ge=null:he?ge=O.actionData:ge=null;let _e=B.loaderData?bg(O.loaderData,B.loaderData,B.matches||[],B.errors):O.loaderData,Ce=O.blockers;Ce.size>0&&(Ce=new Map(Ce),Ce.forEach((Ne,De)=>Ce.set(De,ol)));let be=U?!1:mi(z,B.matches||O.matches),Te=pe===!0||O.navigation.formMethod!=null&&rn(O.navigation.formMethod)&&z.state?._isRedirect!==!0;v&&(d=v,v=void 0),U||I==="POP"||(I==="PUSH"?t.history.push(z,z.state):I==="REPLACE"&&t.history.replace(z,z.state));let Ee;if(I==="POP"){let Ne=J.get(O.location.pathname);Ne&&Ne.has(z.pathname)?Ee={currentLocation:O.location,nextLocation:z}:J.has(z.pathname)&&(Ee={currentLocation:z,nextLocation:O.location})}else if(de){let Ne=J.get(O.location.pathname);Ne?Ne.add(z.pathname):(Ne=new Set([z.pathname]),J.set(O.location.pathname,Ne)),Ee={currentLocation:O.location,nextLocation:z}}te({...B,actionData:ge,loaderData:_e,historyAction:I,location:z,initialized:!0,renderFallback:!1,navigation:M2,revalidation:"idle",restoreScrollPosition:be,preventScrollReset:Te,blockers:Ce},{viewTransitionOpts:Ee,flushSync:X===!0}),I="POP",pe=!1,de=!1,U=!1,H=!1,re?.resolve(),re=null,we?.resolve(),we=null}async function Ze(z,B){if(re?.resolve(),re=null,typeof z=="number"){re||(re=wg());let dt=re.promise;return t.history.go(z),dt}let X=Cf(O.location,O.matches,m,z,B?.fromRouteId,B?.relative),{path:he,submission:ge,error:_e}=fg(!1,X,B),Ce;B?.unstable_mask&&(Ce={pathname:"",search:"",hash:"",...typeof B.unstable_mask=="string"?Aa(B.unstable_mask):{...O.location.unstable_mask,...B.unstable_mask}});let be=O.location,Te=vl(be,he,B&&B.state,void 0,Ce);Te={...Te,...t.history.encodeLocation(Te)};let Ee=B&&B.replace!=null?B.replace:void 0,Ne="PUSH";Ee===!0?Ne="REPLACE":Ee===!1||ge!=null&&rn(ge.formMethod)&&ge.formAction===O.location.pathname+O.location.search&&(Ne="REPLACE");let De=B&&"preventScrollReset"in B?B.preventScrollReset===!0:void 0,We=(B&&B.flushSync)===!0,Be=Mr({currentLocation:be,nextLocation:Te,historyAction:Ne});if(Be){Ea(Be,{state:"blocked",location:Te,proceed(){Ea(Be,{state:"proceeding",proceed:void 0,reset:void 0,location:Te}),Ze(z,B)},reset(){let dt=new Map(O.blockers);dt.set(Be,ol),te({blockers:dt})}});return}await Je(Ne,Te,{submission:ge,pendingError:_e,preventScrollReset:De,replace:B&&B.replace,enableViewTransition:B&&B.viewTransition,flushSync:We,callSiteDefaultShouldRevalidate:B&&B.unstable_defaultShouldRevalidate})}function At(){we||(we=wg()),ve(),te({revalidation:"loading"});let z=we.promise;return O.navigation.state==="submitting"?z:O.navigation.state==="idle"?(Je(O.historyAction,O.location,{startUninterruptedRevalidation:!0}),z):(Je(I||O.historyAction,O.navigation.location,{overrideNavigation:O.navigation,enableViewTransition:de===!0}),z)}async function Je(z,B,X){ce&&ce.abort(),ce=null,I=z,U=(X&&X.startUninterruptedRevalidation)===!0,hc(O.location,O.matches),pe=(X&&X.preventScrollReset)===!0,de=(X&&X.enableViewTransition)===!0;let he=v||d,ge=X&&X.overrideNavigation,_e=X?.initialHydration&&O.matches&&O.matches.length>0&&!R?O.matches:Ha(he,B,m),Ce=(X&&X.flushSync)===!0;if(_e&&O.initialized&&!H&&bE(O.location,B)&&!(X&&X.submission&&rn(X.submission.formMethod))){pt(B,{matches:_e},{flushSync:Ce});return}let be=Qa(_e,he,B.pathname);if(be.active&&be.matches&&(_e=be.matches),!_e){let{error:Ct,notFoundMatches:Rt,route:Ke}=Xn(B.pathname);pt(B,{matches:Rt,loaderData:{},errors:{[Ke.id]:Ct}},{flushSync:Ce});return}ce=new AbortController;let Te=Ko(t.history,B,ce.signal,X&&X.submission),Ee=t.getContext?await t.getContext():new og,Ne;if(X&&X.pendingError)Ne=[Cr(_e).route.id,{type:"error",error:X.pendingError}];else if(X&&X.submission&&rn(X.submission.formMethod)){let Ct=await en(Te,B,X.submission,_e,Ee,be.active,X&&X.initialHydration===!0,{replace:X.replace,flushSync:Ce});if(Ct.shortCircuited)return;if(Ct.pendingActionResult){let[Rt,Ke]=Ct.pendingActionResult;if(Rn(Ke)&&yl(Ke.error)&&Ke.error.status===404){ce=null,pt(B,{matches:Ct.matches,loaderData:{},errors:{[Rt]:Ke.error}});return}}_e=Ct.matches||_e,Ne=Ct.pendingActionResult,ge=D2(B,X.submission),Ce=!1,be.active=!1,Te=Ko(t.history,Te.url,Te.signal)}let{shortCircuited:De,matches:We,loaderData:Be,errors:dt}=await yn(Te,B,_e,Ee,be.active,ge,X&&X.submission,X&&X.fetcherSubmission,X&&X.replace,X&&X.initialHydration===!0,Ce,Ne,X&&X.callSiteDefaultShouldRevalidate);De||(ce=null,pt(B,{matches:We||_e,...Eg(Ne),loaderData:Be,errors:dt}))}async function en(z,B,X,he,ge,_e,Ce,be={}){ve();let Te=ME(B,X);if(te({navigation:Te},{flushSync:be.flushSync===!0}),_e){let De=await sa(he,B.pathname,z.signal);if(De.type==="aborted")return{shortCircuited:!0};if(De.type==="error"){if(De.partialMatches.length===0){let{matches:Be,route:dt}=Js(d);return{matches:Be,pendingActionResult:[dt.id,{type:"error",error:De.error}]}}let We=Cr(De.partialMatches).route.id;return{matches:De.partialMatches,pendingActionResult:[We,{type:"error",error:De.error}]}}else if(De.matches)he=De.matches;else{let{notFoundMatches:We,error:Be,route:dt}=Xn(B.pathname);return{matches:We,pendingActionResult:[dt.id,{type:"error",error:Be}]}}}let Ee,Ne=gu(he,B);if(!Ne.route.action&&!Ne.route.lazy)Ee={type:"error",error:Bn(405,{method:z.method,pathname:B.pathname,routeId:Ne.route.id})};else{let De=Jo(u,c,z,B,he,Ne,Ce?[]:i,ge),We=await ye(z,B,De,ge,null);if(Ee=We[Ne.route.id],!Ee){for(let Be of he)if(We[Be.route.id]){Ee=We[Be.route.id];break}}if(z.signal.aborted)return{shortCircuited:!0}}if(Kr(Ee)){let De;return be&&be.replace!=null?De=be.replace:De=yg(Ee.response.headers.get("Location"),new URL(z.url),m,t.history)===O.location.pathname+O.location.search,await Kn(z,Ee,!0,{submission:X,replace:De}),{shortCircuited:!0}}if(Rn(Ee)){let De=Cr(he,Ne.route.id);return(be&&be.replace)!==!0&&(I="PUSH"),{matches:he,pendingActionResult:[De.route.id,Ee,Ne.route.id]}}return{matches:he,pendingActionResult:[Ne.route.id,Ee]}}async function yn(z,B,X,he,ge,_e,Ce,be,Te,Ee,Ne,De,We){let Be=_e||D2(B,Ce),dt=Ce||be||xg(Be),Ct=!U&&!Ee;if(ge){if(Ct){let Nt=On(De);te({navigation:Be,...Nt!==void 0?{actionData:Nt}:{}},{flushSync:Ne})}let $e=await sa(X,B.pathname,z.signal);if($e.type==="aborted")return{shortCircuited:!0};if($e.type==="error"){if($e.partialMatches.length===0){let{matches:nn,route:Pt}=Js(d);return{matches:nn,loaderData:{},errors:{[Pt.id]:$e.error}}}let Nt=Cr($e.partialMatches).route.id;return{matches:$e.partialMatches,loaderData:{},errors:{[Nt]:$e.error}}}else if($e.matches)X=$e.matches;else{let{error:Nt,notFoundMatches:nn,route:Pt}=Xn(B.pathname);return{matches:nn,loaderData:{},errors:{[Pt.id]:Nt}}}}let Rt=v||d,{dsMatches:Ke,revalidatingFetchers:Ut}=dg(z,he,u,c,t.history,O,X,dt,B,Ee?[]:i,Ee===!0,H,K,Se,ie,ne,Rt,m,t.patchRoutesOnNavigation!=null,De,We);if(L=++se,!t.dataStrategy&&!Ke.some($e=>$e.shouldLoad)&&!Ke.some($e=>$e.route.middleware&&$e.route.middleware.length>0)&&Ut.length===0){let $e=kl();return pt(B,{matches:X,loaderData:{},errors:De&&Rn(De[1])?{[De[0]]:De[1].error}:null,...Eg(De),...$e?{fetchers:new Map(O.fetchers)}:{}},{flushSync:Ne}),{shortCircuited:!0}}if(Ct){let $e={};if(!ge){$e.navigation=Be;let Nt=On(De);Nt!==void 0&&($e.actionData=Nt)}Ut.length>0&&($e.fetchers=la(Ut)),te($e,{flushSync:Ne})}Ut.forEach($e=>{qt($e.key),$e.controller&&G.set($e.key,$e.controller)});let vt=()=>Ut.forEach($e=>qt($e.key));ce&&ce.signal.addEventListener("abort",vt);let{loaderResults:Ka,fetcherResults:Zn}=await at(Ke,Ut,z,B,he);if(z.signal.aborted)return{shortCircuited:!0};ce&&ce.signal.removeEventListener("abort",vt),Ut.forEach($e=>G.delete($e.key));let Gt=Ws(Ka);if(Gt)return await Kn(z,Gt.result,!0,{replace:Te}),{shortCircuited:!0};if(Gt=Ws(Zn),Gt)return ne.add(Gt.key),await Kn(z,Gt.result,!0,{replace:Te}),{shortCircuited:!0};let{loaderData:ua,errors:Dr}=Cg(O,X,Ka,De,Ut,Zn);Ee&&O.errors&&(Dr={...O.errors,...Dr});let ca=kl(),Or=zl(L),so=ca||Or||Ut.length>0;return{matches:X,loaderData:ua,errors:Dr,...so?{fetchers:new Map(O.fetchers)}:{}}}function On(z){if(z&&!Rn(z[1]))return{[z[0]]:z[1].data};if(O.actionData)return Object.keys(O.actionData).length===0?null:O.actionData}function la(z){return z.forEach(B=>{let X=O.fetchers.get(B.key),he=il(void 0,X?X.data:void 0);O.fetchers.set(B.key,he)}),new Map(O.fetchers)}async function Nn(z,B,X,he){qt(z);let ge=(he&&he.flushSync)===!0,_e=v||d,Ce=Cf(O.location,O.matches,m,X,B,he?.relative),be=Ha(_e,Ce,m),Te=Qa(be,_e,Ce);if(Te.active&&Te.matches&&(be=Te.matches),!be){He(z,B,Bn(404,{pathname:Ce}),{flushSync:ge});return}let{path:Ee,submission:Ne,error:De}=fg(!0,Ce,he);if(De){He(z,B,De,{flushSync:ge});return}let We=t.getContext?await t.getContext():new og,Be=(he&&he.preventScrollReset)===!0;if(Ne&&rn(Ne.formMethod)){await Ue(z,B,Ee,be,We,Te.active,ge,Be,Ne,he&&he.unstable_defaultShouldRevalidate);return}ie.set(z,{routeId:B,path:Ee}),await kt(z,B,Ee,be,We,Te.active,ge,Be,Ne)}async function Ue(z,B,X,he,ge,_e,Ce,be,Te,Ee){ve(),ie.delete(z);let Ne=O.fetchers.get(z);je(z,DE(Te,Ne),{flushSync:Ce});let De=new AbortController,We=Ko(t.history,X,De.signal,Te);if(_e){let bt=await sa(he,new URL(We.url).pathname,We.signal,z);if(bt.type==="aborted")return;if(bt.type==="error"){He(z,B,bt.error,{flushSync:Ce});return}else if(bt.matches)he=bt.matches;else{He(z,B,Bn(404,{pathname:X}),{flushSync:Ce});return}}let Be=gu(he,X);if(!Be.route.action&&!Be.route.lazy){let bt=Bn(405,{method:Te.formMethod,pathname:X,routeId:B});He(z,B,bt,{flushSync:Ce});return}G.set(z,De);let dt=se,Ct=Jo(u,c,We,X,he,Be,i,ge),Rt=await ye(We,X,Ct,ge,z),Ke=Rt[Be.route.id];if(!Ke){for(let bt of Ct)if(Rt[bt.route.id]){Ke=Rt[bt.route.id];break}}if(We.signal.aborted){G.get(z)===De&&G.delete(z);return}if(Se.has(z)){if(Kr(Ke)||Rn(Ke)){je(z,Ia(void 0));return}}else{if(Kr(Ke))if(G.delete(z),L>dt){je(z,Ia(void 0));return}else return ne.add(z),je(z,il(Te)),Kn(We,Ke,!1,{fetcherSubmission:Te,preventScrollReset:be});if(Rn(Ke)){He(z,B,Ke.error);return}}let Ut=O.navigation.location||O.location,vt=Ko(t.history,Ut,De.signal),Ka=v||d,Zn=O.navigation.state!=="idle"?Ha(Ka,O.navigation.location,m):O.matches;Ie(Zn,"Didn't find any matches after fetcher action");let Gt=++se;$.set(z,Gt);let ua=il(Te,Ke.data);O.fetchers.set(z,ua);let{dsMatches:Dr,revalidatingFetchers:ca}=dg(vt,ge,u,c,t.history,O,Zn,Te,Ut,i,!1,H,K,Se,ie,ne,Ka,m,t.patchRoutesOnNavigation!=null,[Be.route.id,Ke],Ee);ca.filter(bt=>bt.key!==z).forEach(bt=>{let uo=bt.key,co=O.fetchers.get(uo),Hl=il(void 0,co?co.data:void 0);O.fetchers.set(uo,Hl),qt(uo),bt.controller&&G.set(uo,bt.controller)}),te({fetchers:new Map(O.fetchers)});let Or=()=>ca.forEach(bt=>qt(bt.key));De.signal.addEventListener("abort",Or);let{loaderResults:so,fetcherResults:$e}=await at(Dr,ca,vt,Ut,ge);if(De.signal.aborted)return;if(De.signal.removeEventListener("abort",Or),$.delete(z),G.delete(z),ca.forEach(bt=>G.delete(bt.key)),O.fetchers.has(z)){let bt=Ia(Ke.data);O.fetchers.set(z,bt)}let Nt=Ws(so);if(Nt)return Kn(vt,Nt.result,!1,{preventScrollReset:be});if(Nt=Ws($e),Nt)return ne.add(Nt.key),Kn(vt,Nt.result,!1,{preventScrollReset:be});let{loaderData:nn,errors:Pt}=Cg(O,Zn,so,void 0,ca,$e);zl(Gt),O.navigation.state==="loading"&&Gt>L?(Ie(I,"Expected pending action"),ce&&ce.abort(),pt(O.navigation.location,{matches:Zn,loaderData:nn,errors:Pt,fetchers:new Map(O.fetchers)})):(te({errors:Pt,loaderData:bg(O.loaderData,nn,Zn,Pt),fetchers:new Map(O.fetchers)}),H=!1)}async function kt(z,B,X,he,ge,_e,Ce,be,Te){let Ee=O.fetchers.get(z);je(z,il(Te,Ee?Ee.data:void 0),{flushSync:Ce});let Ne=new AbortController,De=Ko(t.history,X,Ne.signal);if(_e){let Ke=await sa(he,new URL(De.url).pathname,De.signal,z);if(Ke.type==="aborted")return;if(Ke.type==="error"){He(z,B,Ke.error,{flushSync:Ce});return}else if(Ke.matches)he=Ke.matches;else{He(z,B,Bn(404,{pathname:X}),{flushSync:Ce});return}}let We=gu(he,X);G.set(z,Ne);let Be=se,dt=Jo(u,c,De,X,he,We,i,ge),Rt=(await ye(De,X,dt,ge,z))[We.route.id];if(G.get(z)===Ne&&G.delete(z),!De.signal.aborted){if(Se.has(z)){je(z,Ia(void 0));return}if(Kr(Rt))if(L>Be){je(z,Ia(void 0));return}else{ne.add(z),await Kn(De,Rt,!1,{preventScrollReset:be});return}if(Rn(Rt)){He(z,B,Rt.error);return}je(z,Ia(Rt.data))}}async function Kn(z,B,X,{submission:he,fetcherSubmission:ge,preventScrollReset:_e,replace:Ce}={}){X||(re?.resolve(),re=null),B.response.headers.has("X-Remix-Revalidate")&&(H=!0);let be=B.response.headers.get("Location");Ie(be,"Expected a Location header on the redirect Response"),be=yg(be,new URL(z.url),m,t.history);let Te=vl(O.location,be,{_isRedirect:!0});if(o){let dt=!1;if(B.response.headers.has("X-Remix-Reload-Document"))dt=!0;else if(ed(be)){const Ct=iy(be,!0);dt=Ct.origin!==a.location.origin||Dn(Ct.pathname,m)==null}if(dt){Ce?a.location.replace(be):a.location.assign(be);return}}ce=null;let Ee=Ce===!0||B.response.headers.has("X-Remix-Replace")?"REPLACE":"PUSH",{formMethod:Ne,formAction:De,formEncType:We}=O.navigation;!he&&!ge&&Ne&&De&&We&&(he=xg(O.navigation));let Be=he||ge;if(oE.has(B.response.status)&&Be&&rn(Be.formMethod))await Je(Ee,Te,{submission:{...Be,formAction:be},preventScrollReset:_e||pe,enableViewTransition:X?de:void 0});else{let dt=D2(Te,he);await Je(Ee,Te,{overrideNavigation:dt,fetcherSubmission:ge,preventScrollReset:_e||pe,enableViewTransition:X?de:void 0})}}async function ye(z,B,X,he,ge){let _e,Ce={};try{_e=await mE(A,z,B,X,ge,he,!1)}catch(be){return X.filter(Te=>Te.shouldLoad).forEach(Te=>{Ce[Te.route.id]={type:"error",error:be}}),Ce}if(z.signal.aborted)return Ce;if(!rn(z.method))for(let be of X){if(_e[be.route.id]?.type==="error")break;!_e.hasOwnProperty(be.route.id)&&!O.loaderData.hasOwnProperty(be.route.id)&&(!O.errors||!O.errors.hasOwnProperty(be.route.id))&&be.shouldCallHandler()&&(_e[be.route.id]={type:"error",result:new Error(`No result returned from dataStrategy for route ${be.route.id}`)})}for(let[be,Te]of Object.entries(_e))if(wE(Te)){let Ee=Te.result;Ce[be]={type:"redirect",response:AE(Ee,z,be,X,m)}}else Ce[be]=await yE(Te);return Ce}async function at(z,B,X,he,ge){let _e=ye(X,he,z,ge,null),Ce=Promise.all(B.map(async Ee=>{if(Ee.matches&&Ee.match&&Ee.request&&Ee.controller){let De=(await ye(Ee.request,Ee.path,Ee.matches,ge,Ee.key))[Ee.match.route.id];return{[Ee.key]:De}}else return Promise.resolve({[Ee.key]:{type:"error",error:Bn(404,{pathname:Ee.path})}})})),be=await _e,Te=(await Ce).reduce((Ee,Ne)=>Object.assign(Ee,Ne),{});return{loaderResults:be,fetcherResults:Te}}function ve(){H=!0,ie.forEach((z,B)=>{G.has(B)&&K.add(B),qt(B)})}function je(z,B,X={}){O.fetchers.set(z,B),te({fetchers:new Map(O.fetchers)},{flushSync:(X&&X.flushSync)===!0})}function He(z,B,X,he={}){let ge=Cr(O.matches,B);zt(z),te({errors:{[ge.route.id]:X},fetchers:new Map(O.fetchers)},{flushSync:(he&&he.flushSync)===!0})}function xt(z){return Ae.set(z,(Ae.get(z)||0)+1),Se.has(z)&&Se.delete(z),O.fetchers.get(z)||iE}function rt(z,B){qt(z,B?.reason),je(z,Ia(null))}function zt(z){let B=O.fetchers.get(z);G.has(z)&&!(B&&B.state==="loading"&&$.has(z))&&qt(z),ie.delete(z),$.delete(z),ne.delete(z),Se.delete(z),K.delete(z),O.fetchers.delete(z)}function mt(z){let B=(Ae.get(z)||0)-1;B<=0?(Ae.delete(z),Se.add(z)):Ae.set(z,B),te({fetchers:new Map(O.fetchers)})}function qt(z,B){let X=G.get(z);X&&(X.abort(B),G.delete(z))}function tn(z){for(let B of z){let X=xt(B),he=Ia(X.data);O.fetchers.set(B,he)}}function kl(){let z=[],B=!1;for(let X of ne){let he=O.fetchers.get(X);Ie(he,`Expected fetcher: ${X}`),he.state==="loading"&&(ne.delete(X),z.push(X),B=!0)}return tn(z),B}function zl(z){let B=[];for(let[X,he]of $)if(he<z){let ge=O.fetchers.get(X);Ie(ge,`Expected fetcher: ${X}`),ge.state==="loading"&&(qt(X),$.delete(X),B.push(X))}return tn(B),B.length>0}function dc(z,B){let X=O.blockers.get(z)||ol;return ue.get(z)!==B&&ue.set(z,B),X}function Tr(z){O.blockers.delete(z),ue.delete(z)}function Ea(z,B){let X=O.blockers.get(z)||ol;Ie(X.state==="unblocked"&&B.state==="blocked"||X.state==="blocked"&&B.state==="blocked"||X.state==="blocked"&&B.state==="proceeding"||X.state==="blocked"&&B.state==="unblocked"||X.state==="proceeding"&&B.state==="unblocked",`Invalid blocker state transition: ${X.state} -> ${B.state}`);let he=new Map(O.blockers);he.set(z,B),te({blockers:he})}function Mr({currentLocation:z,nextLocation:B,historyAction:X}){if(ue.size===0)return;ue.size>1&&Dt(!1,"A router only supports one blocker at a time");let he=Array.from(ue.entries()),[ge,_e]=he[he.length-1],Ce=O.blockers.get(ge);if(!(Ce&&Ce.state==="proceeding")&&_e({currentLocation:z,nextLocation:B,historyAction:X}))return ge}function Xn(z){let B=Bn(404,{pathname:z}),X=v||d,{matches:he,route:ge}=Js(X);return{notFoundMatches:he,route:ge,error:B}}function lo(z,B,X){if(S=z,w=B,x=X||null,!D&&O.navigation===M2){D=!0;let he=mi(O.location,O.matches);he!=null&&te({restoreScrollPosition:he})}return()=>{S=null,w=null,x=null}}function Ya(z,B){return x&&x(z,B.map(he=>ly(he,O.loaderData)))||z.key}function hc(z,B){if(S&&w){let X=Ya(z,B);S[X]=w()}}function mi(z,B){if(S){let X=Ya(z,B),he=S[X];if(typeof he=="number")return he}return null}function Qa(z,B,X){if(t.patchRoutesOnNavigation)if(z){if(Object.keys(z[0].params).length>0)return{active:!0,matches:ul(B,X,m,!0)}}else return{active:!0,matches:ul(B,X,m,!0)||[]};return{active:!1,matches:null}}async function sa(z,B,X,he){if(!t.patchRoutesOnNavigation)return{type:"success",matches:z};let ge=z;for(;;){let _e=v==null,Ce=v||d,be=c;try{await t.patchRoutesOnNavigation({signal:X,path:B,matches:ge,fetcherKey:he,patch:(Ne,De)=>{X.aborted||hg(Ne,De,Ce,be,u,!1)}})}catch(Ne){return{type:"error",error:Ne,partialMatches:ge}}finally{_e&&!X.aborted&&(d=[...d])}if(X.aborted)return{type:"aborted"};let Te=Ha(Ce,B,m),Ee=null;if(Te){if(Object.keys(Te[0].params).length===0)return{type:"success",matches:Te};if(Ee=ul(Ce,B,m,!0),!(Ee&&ge.length<Ee.length&&Ul(ge,Ee.slice(0,ge.length))))return{type:"success",matches:Te}}if(Ee||(Ee=ul(Ce,B,m,!0)),!Ee||Ul(ge,Ee))return{type:"success",matches:null};ge=Ee}}function Ul(z,B){return z.length===B.length&&z.every((X,he)=>X.route.id===B[he].route.id)}function Pl(z){c={},v=gl(z,u,void 0,c)}function Il(z,B,X=!1){let he=v==null;hg(z,B,v||d,c,u,X),he&&(d=[...d],te({}))}return F={get basename(){return m},get future(){return p},get state(){return O},get routes(){return d},get window(){return a},initialize:lt,subscribe:W,enableScrollRestoration:lo,navigate:Ze,fetch:Nn,revalidate:At,createHref:z=>t.history.createHref(z),encodeLocation:z=>t.history.encodeLocation(z),getFetcher:xt,resetFetcher:rt,deleteFetcher:mt,dispose:Xe,getBlocker:dc,deleteBlocker:Tr,patchRoutes:Il,_internalFetchControllers:G,_internalSetRoutes:Pl,_internalSetStateDoNotUseOrYouWillBreakYourApp(z){te(z)}},t.unstable_instrumentations&&(F=Zb(F,t.unstable_instrumentations.map(z=>z.router).filter(Boolean))),F}function uE(t){return t!=null&&("formData"in t&&t.formData!=null||"body"in t&&t.body!==void 0)}function Cf(t,a,o,i,s,u){let c,d;if(s){c=[];for(let m of a)if(c.push(m),m.route.id===s){d=m;break}}else c=a,d=a[a.length-1];let v=Pu(i||".",td(c),Dn(t.pathname,o)||t.pathname,u==="path");if(i==null&&(v.search=t.search,v.hash=t.hash),(i==null||i===""||i===".")&&d){let m=rd(v.search);if(d.route.index&&!m)v.search=v.search?v.search.replace(/^\?/,"?index&"):"?index";else if(!d.route.index&&m){let A=new URLSearchParams(v.search),p=A.getAll("index");A.delete("index"),p.filter(b=>b).forEach(b=>A.append("index",b));let C=A.toString();v.search=C?`?${C}`:""}}return o!=="/"&&(v.pathname=qb({basename:o,pathname:v.pathname})),ya(v)}function fg(t,a,o){if(!o||!uE(o))return{path:a};if(o.formMethod&&!TE(o.formMethod))return{path:a,error:Bn(405,{method:o.formMethod})};let i=()=>({path:a,error:Bn(400,{type:"invalid-body"})}),u=(o.formMethod||"get").toUpperCase(),c=Ry(a);if(o.body!==void 0){if(o.formEncType==="text/plain"){if(!rn(u))return i();let p=typeof o.body=="string"?o.body:o.body instanceof FormData||o.body instanceof URLSearchParams?Array.from(o.body.entries()).reduce((C,[b,S])=>`${C}${b}=${S} |
|
| 11 | + | `,""):String(o.body);return{path:a,submission:{formMethod:u,formAction:c,formEncType:o.formEncType,formData:void 0,json:void 0,text:p}}}else if(o.formEncType==="application/json"){if(!rn(u))return i();try{let p=typeof o.body=="string"?JSON.parse(o.body):o.body;return{path:a,submission:{formMethod:u,formAction:c,formEncType:o.formEncType,formData:void 0,json:p,text:void 0}}}catch{return i()}}}Ie(typeof FormData=="function","FormData is not available in this environment");let d,v;if(o.formData)d=Ef(o.formData),v=o.formData;else if(o.body instanceof FormData)d=Ef(o.body),v=o.body;else if(o.body instanceof URLSearchParams)d=o.body,v=Ag(d);else if(o.body==null)d=new URLSearchParams,v=new FormData;else try{d=new URLSearchParams(o.body),v=Ag(d)}catch{return i()}let m={formMethod:u,formAction:c,formEncType:o&&o.formEncType||"application/x-www-form-urlencoded",formData:v,json:void 0,text:void 0};if(rn(m.formMethod))return{path:a,submission:m};let A=Aa(a);return t&&A.search&&rd(A.search)&&d.append("index",""),A.search=`?${d}`,{path:ya(A),submission:m}}function dg(t,a,o,i,s,u,c,d,v,m,A,p,C,b,S,x,w,D,T,R,_){let N=R?Rn(R[1])?R[1].error:R[1].data:void 0,j=s.createURL(u.location),F=s.createURL(v),O;if(A&&u.errors){let fe=Object.keys(u.errors)[0];O=c.findIndex(U=>U.route.id===fe)}else if(R&&Rn(R[1])){let fe=R[0];O=c.findIndex(U=>U.route.id===fe)-1}let I=R?R[1].statusCode:void 0,re=I&&I>=400,pe={currentUrl:j,currentParams:u.matches[0]?.params||{},nextUrl:F,nextParams:c[0].params,...d,actionResult:N,actionStatus:I},ce=wl(c),de=c.map((fe,U)=>{let{route:H}=fe,K=null;if(O!=null&&U>O)K=!1;else if(H.lazy)K=!0;else if(!nd(H))K=!1;else if(A){let{shouldLoad:$}=Cy(H,u.loaderData,u.errors);K=$}else cE(u.loaderData,u.matches[U],fe)&&(K=!0);if(K!==null)return bf(o,i,t,v,ce,fe,m,a,K);let G=!1;typeof _=="boolean"?G=_:re?G=!1:(p||j.pathname+j.search===F.pathname+F.search||j.search!==F.search||fE(u.matches[U],fe))&&(G=!0);let se={...pe,defaultShouldRevalidate:G},L=pl(fe,se);return bf(o,i,t,v,ce,fe,m,a,L,se,_)}),J=[];return S.forEach((fe,U)=>{if(A||!c.some(ie=>ie.route.id===fe.routeId)||b.has(U))return;let H=u.fetchers.get(U),K=H&&H.state!=="idle"&&H.data===void 0,G=Ha(w,fe.path,D);if(!G){if(T&&K)return;J.push({key:U,routeId:fe.routeId,path:fe.path,matches:null,match:null,request:null,controller:null});return}if(x.has(U))return;let se=gu(G,fe.path),L=new AbortController,$=Ko(s,fe.path,L.signal),ne=null;if(C.has(U))C.delete(U),ne=Jo(o,i,$,fe.path,G,se,m,a);else if(K)p&&(ne=Jo(o,i,$,fe.path,G,se,m,a));else{let ie;typeof _=="boolean"?ie=_:re?ie=!1:ie=p;let Ae={...pe,defaultShouldRevalidate:ie};pl(se,Ae)&&(ne=Jo(o,i,$,fe.path,G,se,m,a,Ae))}ne&&J.push({key:U,routeId:fe.routeId,path:fe.path,matches:ne,match:se,request:$,controller:L})}),{dsMatches:de,revalidatingFetchers:J}}function nd(t){return t.loader!=null||t.middleware!=null&&t.middleware.length>0}function Cy(t,a,o){if(t.lazy)return{shouldLoad:!0,renderFallback:!0};if(!nd(t))return{shouldLoad:!1,renderFallback:!1};let i=a!=null&&t.id in a,s=o!=null&&o[t.id]!==void 0;if(!i&&s)return{shouldLoad:!1,renderFallback:!1};if(typeof t.loader=="function"&&t.loader.hydrate===!0)return{shouldLoad:!0,renderFallback:!i};let u=!i&&!s;return{shouldLoad:u,renderFallback:u}}function cE(t,a,o){let i=!a||o.route.id!==a.route.id,s=!t.hasOwnProperty(o.route.id);return i||s}function fE(t,a){let o=t.route.path;return t.pathname!==a.pathname||o!=null&&o.endsWith("*")&&t.params["*"]!==a.params["*"]}function pl(t,a){if(t.route.shouldRevalidate){let o=t.route.shouldRevalidate(a);if(typeof o=="boolean")return o}return a.defaultShouldRevalidate}function hg(t,a,o,i,s,u){let c;if(t){let m=i[t];Ie(m,`No route found to patch children into: routeId = ${t}`),m.children||(m.children=[]),c=m.children}else c=o;let d=[],v=[];if(a.forEach(m=>{let A=c.find(p=>by(m,p));A?v.push({existingRoute:A,newRoute:m}):d.push(m)}),d.length>0){let m=gl(d,s,[t||"_","patch",String(c?.length||"0")],i);c.push(...m)}if(u&&v.length>0)for(let m=0;m<v.length;m++){let{existingRoute:A,newRoute:p}=v[m],C=A,[b]=gl([p],s,[],{},!0);Object.assign(C,{element:b.element?b.element:C.element,errorElement:b.errorElement?b.errorElement:C.errorElement,hydrateFallbackElement:b.hydrateFallbackElement?b.hydrateFallbackElement:C.hydrateFallbackElement})}}function by(t,a){return"id"in t&&"id"in a&&t.id===a.id?!0:t.index===a.index&&t.path===a.path&&t.caseSensitive===a.caseSensitive?(!t.children||t.children.length===0)&&(!a.children||a.children.length===0)?!0:t.children?.every((o,i)=>a.children?.some(s=>by(o,s)))??!1:!1}var pg=new WeakMap,Ey=({key:t,route:a,manifest:o,mapRouteProperties:i})=>{let s=o[a.id];if(Ie(s,"No route found in manifest"),!s.lazy||typeof s.lazy!="object")return;let u=s.lazy[t];if(!u)return;let c=pg.get(s);c||(c={},pg.set(s,c));let d=c[t];if(d)return d;let v=(async()=>{let m=Db(t),p=s[t]!==void 0&&t!=="hasErrorBoundary";if(m)Dt(!m,"Route property "+t+" is not a supported lazy route property. This property will be ignored."),c[t]=Promise.resolve();else if(p)Dt(!1,`Route "${s.id}" has a static property "${t}" defined. The lazy property will be ignored.`);else{let C=await u();C!=null&&(Object.assign(s,{[t]:C}),Object.assign(s,i(s)))}typeof s.lazy=="object"&&(s.lazy[t]=void 0,Object.values(s.lazy).every(C=>C===void 0)&&(s.lazy=void 0))})();return c[t]=v,v},mg=new WeakMap;function dE(t,a,o,i,s){let u=o[t.id];if(Ie(u,"No route found in manifest"),!t.lazy)return{lazyRoutePromise:void 0,lazyHandlerPromise:void 0};if(typeof t.lazy=="function"){let A=mg.get(u);if(A)return{lazyRoutePromise:A,lazyHandlerPromise:A};let p=(async()=>{Ie(typeof t.lazy=="function","No lazy route function found");let C=await t.lazy(),b={};for(let S in C){let x=C[S];if(x===void 0)continue;let w=Nb(S),T=u[S]!==void 0&&S!=="hasErrorBoundary";w?Dt(!w,"Route property "+S+" is not a supported property to be returned from a lazy route function. This property will be ignored."):T?Dt(!T,`Route "${u.id}" has a static property "${S}" defined but its lazy function is also returning a value for this property. The lazy route property "${S}" will be ignored.`):b[S]=x}Object.assign(u,b),Object.assign(u,{...i(u),lazy:void 0})})();return mg.set(u,p),p.catch(()=>{}),{lazyRoutePromise:p,lazyHandlerPromise:p}}let c=Object.keys(t.lazy),d=[],v;for(let A of c){if(s&&s.includes(A))continue;let p=Ey({key:A,route:t,manifest:o,mapRouteProperties:i});p&&(d.push(p),A===a&&(v=p))}let m=d.length>0?Promise.all(d).then(()=>{}):void 0;return m?.catch(()=>{}),v?.catch(()=>{}),{lazyRoutePromise:m,lazyHandlerPromise:v}}async function vg(t){let a=t.matches.filter(s=>s.shouldLoad),o={};return(await Promise.all(a.map(s=>s.resolve()))).forEach((s,u)=>{o[a[u].route.id]=s}),o}async function hE(t){return t.matches.some(a=>a.route.middleware)?Sy(t,()=>vg(t)):vg(t)}function Sy(t,a){return pE(t,a,i=>{if(RE(i))throw i;return i},SE,o);function o(i,s,u){if(u)return Promise.resolve(Object.assign(u.value,{[s]:{type:"error",result:i}}));{let{matches:c}=t,d=Math.min(Math.max(c.findIndex(m=>m.route.id===s),0),Math.max(c.findIndex(m=>m.shouldCallHandler()),0)),v=Cr(c,c[d].route.id).route.id;return Promise.resolve({[v]:{type:"error",result:i}})}}}async function pE(t,a,o,i,s){let{matches:u,...c}=t,d=u.flatMap(m=>m.route.middleware?m.route.middleware.map(A=>[m.route.id,A]):[]);return await xy(c,d,a,o,i,s)}async function xy(t,a,o,i,s,u,c=0){let{request:d}=t;if(d.signal.aborted)throw d.signal.reason??new Error(`Request aborted: ${d.method} ${d.url}`);let v=a[c];if(!v)return await o();let[m,A]=v,p,C=async()=>{if(p)throw new Error("You may only call `next()` once per middleware");try{return p={value:await xy(t,a,o,i,s,u,c+1)},p.value}catch(b){return p={value:await u(b,m,p)},p.value}};try{let b=await A(t,C),S=b!=null?i(b):void 0;return s(S)?S:p?S??p.value:(p={value:await C()},p.value)}catch(b){return await u(b,m,p)}}function wy(t,a,o,i,s){let u=Ey({key:"middleware",route:i.route,manifest:a,mapRouteProperties:t}),c=dE(i.route,rn(o.method)?"action":"loader",a,t,s);return{middleware:u,route:c.lazyRoutePromise,handler:c.lazyHandlerPromise}}function bf(t,a,o,i,s,u,c,d,v,m=null,A){let p=!1,C=wy(t,a,o,u,c);return{...u,_lazyPromises:C,shouldLoad:v,shouldRevalidateArgs:m,shouldCallHandler(b){return p=!0,m?typeof A=="boolean"?pl(u,{...m,defaultShouldRevalidate:A}):typeof b=="boolean"?pl(u,{...m,defaultShouldRevalidate:b}):pl(u,m):v},resolve(b){let{lazy:S,loader:x,middleware:w}=u.route,D=p||v||b&&!rn(o.method)&&(S||x),T=w&&w.length>0&&!x&&!S;return D&&(rn(o.method)||!T)?vE({request:o,path:i,unstable_pattern:s,match:u,lazyHandlerPromise:C?.handler,lazyRoutePromise:C?.route,handlerOverride:b,scopedContext:d}):Promise.resolve({type:"data",result:void 0})}}}function Jo(t,a,o,i,s,u,c,d,v=null){return s.map(m=>m.route.id!==u.route.id?{...m,shouldLoad:!1,shouldRevalidateArgs:v,shouldCallHandler:()=>!1,_lazyPromises:wy(t,a,o,m,c),resolve:()=>Promise.resolve({type:"data",result:void 0})}:bf(t,a,o,i,wl(s),m,c,d,!0,v))}async function mE(t,a,o,i,s,u,c){i.some(A=>A._lazyPromises?.middleware)&&await Promise.all(i.map(A=>A._lazyPromises?.middleware));let d={request:a,unstable_url:_y(a,o),unstable_pattern:wl(i),params:i[0].params,context:u,matches:i},m=await t({...d,fetcherKey:s,runClientMiddleware:A=>{let p=d;return Sy(p,()=>A({...p,fetcherKey:s,runClientMiddleware:()=>{throw new Error("Cannot call `runClientMiddleware()` from within an `runClientMiddleware` handler")}}))}});try{await Promise.all(i.flatMap(A=>[A._lazyPromises?.handler,A._lazyPromises?.route]))}catch{}return m}async function vE({request:t,path:a,unstable_pattern:o,match:i,lazyHandlerPromise:s,lazyRoutePromise:u,handlerOverride:c,scopedContext:d}){let v,m,A=rn(t.method),p=A?"action":"loader",C=b=>{let S,x=new Promise((T,R)=>S=R);m=()=>S(),t.signal.addEventListener("abort",m);let w=T=>typeof b!="function"?Promise.reject(new Error(`You cannot call the handler for a route which defines a boolean "${p}" [routeId: ${i.route.id}]`)):b({request:t,unstable_url:_y(t,a),unstable_pattern:o,params:i.params,context:d},...T!==void 0?[T]:[]),D=(async()=>{try{return{type:"data",result:await(c?c(R=>w(R)):w())}}catch(T){return{type:"error",result:T}}})();return Promise.race([D,x])};try{let b=A?i.route.action:i.route.loader;if(s||u)if(b){let S,[x]=await Promise.all([C(b).catch(w=>{S=w}),s,u]);if(S!==void 0)throw S;v=x}else{await s;let S=A?i.route.action:i.route.loader;if(S)[v]=await Promise.all([C(S),u]);else if(p==="action"){let x=new URL(t.url),w=x.pathname+x.search;throw Bn(405,{method:t.method,pathname:w,routeId:i.route.id})}else return{type:"data",result:void 0}}else if(b)v=await C(b);else{let S=new URL(t.url),x=S.pathname+S.search;throw Bn(404,{pathname:x})}}catch(b){return{type:"error",result:b}}finally{m&&t.signal.removeEventListener("abort",m)}return v}async function gE(t){let a=t.headers.get("Content-Type");return a&&/\bapplication\/json\b/.test(a)?t.body==null?null:t.json():t.text()}async function yE(t){let{result:a,type:o}=t;if(ad(a)){let i;try{i=await gE(a)}catch(s){return{type:"error",error:s}}return o==="error"?{type:"error",error:new xl(a.status,a.statusText,i),statusCode:a.status,headers:a.headers}:{type:"data",data:i,statusCode:a.status,headers:a.headers}}return o==="error"?Sg(a)?a.data instanceof Error?{type:"error",error:a.data,statusCode:a.init?.status,headers:a.init?.headers?new Headers(a.init.headers):void 0}:{type:"error",error:EE(a),statusCode:yl(a)?a.status:void 0,headers:a.init?.headers?new Headers(a.init.headers):void 0}:{type:"error",error:a,statusCode:yl(a)?a.status:void 0}:Sg(a)?{type:"data",data:a.data,statusCode:a.init?.status,headers:a.init?.headers?new Headers(a.init.headers):void 0}:{type:"data",data:a}}function AE(t,a,o,i,s){let u=t.headers.get("Location");if(Ie(u,"Redirects returned/thrown from loaders/actions must have a Location header"),!ed(u)){let c=i.slice(0,i.findIndex(d=>d.route.id===o)+1);u=Cf(new URL(a.url),c,s,u),t.headers.set("Location",u)}return t}var gg=["about:","blob:","chrome:","chrome-untrusted:","content:","data:","devtools:","file:","filesystem:","javascript:"];function yg(t,a,o,i){if(ed(t)){let s=t,u=s.startsWith("//")?new URL(a.protocol+s):new URL(s);if(gg.includes(u.protocol))throw new Error("Invalid redirect location");let c=Dn(u.pathname,o)!=null;if(u.origin===a.origin&&c)return u.pathname+u.search+u.hash}try{let s=i.createURL(t);if(gg.includes(s.protocol))throw new Error("Invalid redirect location")}catch{}return t}function Ko(t,a,o,i){let s=t.createURL(Ry(a)).toString(),u={signal:o};if(i&&rn(i.formMethod)){let{formMethod:c,formEncType:d}=i;u.method=c.toUpperCase(),d==="application/json"?(u.headers=new Headers({"Content-Type":d}),u.body=JSON.stringify(i.json)):d==="text/plain"?u.body=i.text:d==="application/x-www-form-urlencoded"&&i.formData?u.body=Ef(i.formData):u.body=i.formData}return new Request(s,u)}function _y(t,a){let o=new URL(t.url),i=typeof a=="string"?Aa(a):a;if(o.pathname=i.pathname||"/",i.search){let s=new URLSearchParams(i.search),u=s.getAll("index");s.delete("index");for(let c of u.filter(Boolean))s.append("index",c);o.search=s.size?`?${s.toString()}`:""}else o.search="";return o.hash=i.hash||"",o}function Ef(t){let a=new URLSearchParams;for(let[o,i]of t.entries())a.append(o,typeof i=="string"?i:i.name);return a}function Ag(t){let a=new FormData;for(let[o,i]of t.entries())a.append(o,i);return a}function CE(t,a,o,i=!1,s=!1){let u={},c=null,d,v=!1,m={},A=o&&Rn(o[1])?o[1].error:void 0;return t.forEach(p=>{if(!(p.route.id in a))return;let C=p.route.id,b=a[C];if(Ie(!Kr(b),"Cannot handle redirect results in processLoaderData"),Rn(b)){let S=b.error;if(A!==void 0&&(S=A,A=void 0),c=c||{},s)c[C]=S;else{let x=Cr(t,C);c[x.route.id]==null&&(c[x.route.id]=S)}i||(u[C]=Ay),v||(v=!0,d=yl(b.error)?b.error.status:500),b.headers&&(m[C]=b.headers)}else u[C]=b.data,b.statusCode&&b.statusCode!==200&&!v&&(d=b.statusCode),b.headers&&(m[C]=b.headers)}),A!==void 0&&o&&(c={[o[0]]:A},o[2]&&(u[o[2]]=void 0)),{loaderData:u,errors:c,statusCode:d||200,loaderHeaders:m}}function Cg(t,a,o,i,s,u){let{loaderData:c,errors:d}=CE(a,o,i);return s.filter(v=>!v.matches||v.matches.some(m=>m.shouldLoad)).forEach(v=>{let{key:m,match:A,controller:p}=v;if(p&&p.signal.aborted)return;let C=u[m];if(Ie(C,"Did not find corresponding fetcher result"),Rn(C)){let b=Cr(t.matches,A?.route.id);d&&d[b.route.id]||(d={...d,[b.route.id]:C.error}),t.fetchers.delete(m)}else if(Kr(C))Ie(!1,"Unhandled fetcher revalidation redirect");else{let b=Ia(C.data);t.fetchers.set(m,b)}}),{loaderData:c,errors:d}}function bg(t,a,o,i){let s=Object.entries(a).filter(([,u])=>u!==Ay).reduce((u,[c,d])=>(u[c]=d,u),{});for(let u of o){let c=u.route.id;if(!a.hasOwnProperty(c)&&t.hasOwnProperty(c)&&u.route.loader&&(s[c]=t[c]),i&&i.hasOwnProperty(c))break}return s}function Eg(t){return t?Rn(t[1])?{actionData:{}}:{actionData:{[t[0]]:t[1].data}}:{}}function Cr(t,a){return(a?t.slice(0,t.findIndex(i=>i.route.id===a)+1):[...t]).reverse().find(i=>i.route.hasErrorBoundary===!0)||t[0]}function Js(t){let a=t.length===1?t[0]:t.find(o=>o.index||!o.path||o.path==="/")||{id:"__shim-error-route__"};return{matches:[{params:{},pathname:"",pathnameBase:"",route:a}],route:a}}function Bn(t,{pathname:a,routeId:o,method:i,type:s,message:u}={}){let c="Unknown Server Error",d="Unknown @remix-run/router error";return t===400?(c="Bad Request",i&&a&&o?d=`You made a ${i} request to "${a}" but did not provide a \`loader\` for route "${o}", so there is no way to handle the request.`:s==="invalid-body"&&(d="Unable to encode submission body")):t===403?(c="Forbidden",d=`Route "${o}" does not match URL "${a}"`):t===404?(c="Not Found",d=`No route matches URL "${a}"`):t===405&&(c="Method Not Allowed",i&&a&&o?d=`You made a ${i.toUpperCase()} request to "${a}" but did not provide an \`action\` for route "${o}", so there is no way to handle the request.`:i&&(d=`Invalid request method "${i.toUpperCase()}"`)),new xl(t||500,c,new Error(d),!0)}function Ws(t){let a=Object.entries(t);for(let o=a.length-1;o>=0;o--){let[i,s]=a[o];if(Kr(s))return{key:i,result:s}}}function Ry(t){let a=typeof t=="string"?Aa(t):t;return ya({...a,hash:""})}function bE(t,a){return t.pathname!==a.pathname||t.search!==a.search?!1:t.hash===""?a.hash!=="":t.hash===a.hash?!0:a.hash!==""}function EE(t){return new xl(t.init?.status??500,t.init?.statusText??"Internal Server Error",t.data)}function SE(t){return t!=null&&typeof t=="object"&&Object.entries(t).every(([a,o])=>typeof a=="string"&&xE(o))}function xE(t){return t!=null&&typeof t=="object"&&"type"in t&&"result"in t&&(t.type==="data"||t.type==="error")}function wE(t){return ad(t.result)&&gy.has(t.result.status)}function Rn(t){return t.type==="error"}function Kr(t){return(t&&t.type)==="redirect"}function Sg(t){return typeof t=="object"&&t!=null&&"type"in t&&"data"in t&&"init"in t&&t.type==="DataWithResponseInit"}function ad(t){return t!=null&&typeof t.status=="number"&&typeof t.statusText=="string"&&typeof t.headers=="object"&&typeof t.body<"u"}function _E(t){return gy.has(t)}function RE(t){return ad(t)&&_E(t.status)&&t.headers.has("Location")}function TE(t){return rE.has(t.toUpperCase())}function rn(t){return nE.has(t.toUpperCase())}function rd(t){return new URLSearchParams(t).getAll("index").some(a=>a==="")}function gu(t,a){let o=typeof a=="string"?Aa(a).search:a.search;if(t[t.length-1].route.index&&rd(o||""))return t[t.length-1];let i=dy(t);return i[i.length-1]}function xg(t){let{formMethod:a,formAction:o,formEncType:i,text:s,formData:u,json:c}=t;if(!(!a||!o||!i)){if(s!=null)return{formMethod:a,formAction:o,formEncType:i,formData:void 0,json:void 0,text:s};if(u!=null)return{formMethod:a,formAction:o,formEncType:i,formData:u,json:void 0,text:void 0};if(c!==void 0)return{formMethod:a,formAction:o,formEncType:i,formData:void 0,json:c,text:void 0}}}function D2(t,a){return a?{state:"loading",location:t,formMethod:a.formMethod,formAction:a.formAction,formEncType:a.formEncType,formData:a.formData,json:a.json,text:a.text}:{state:"loading",location:t,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0}}function ME(t,a){return{state:"submitting",location:t,formMethod:a.formMethod,formAction:a.formAction,formEncType:a.formEncType,formData:a.formData,json:a.json,text:a.text}}function il(t,a){return t?{state:"loading",formMethod:t.formMethod,formAction:t.formAction,formEncType:t.formEncType,formData:t.formData,json:t.json,text:t.text,data:a}:{state:"loading",formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0,data:a}}function DE(t,a){return{state:"submitting",formMethod:t.formMethod,formAction:t.formAction,formEncType:t.formEncType,formData:t.formData,json:t.json,text:t.text,data:a?a.data:void 0}}function Ia(t){return{state:"idle",formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0,data:t}}function OE(t,a){try{let o=t.sessionStorage.getItem(yy);if(o){let i=JSON.parse(o);for(let[s,u]of Object.entries(i||{}))u&&Array.isArray(u)&&a.set(s,new Set(u||[]))}}catch{}}function NE(t,a){if(a.size>0){let o={};for(let[i,s]of a)o[i]=[...s];try{t.sessionStorage.setItem(yy,JSON.stringify(o))}catch(i){Dt(!1,`Failed to save applied view transitions in sessionStorage (${i}).`)}}}function wg(){let t,a,o=new Promise((i,s)=>{t=async u=>{i(u);try{await o}catch{}},a=async u=>{s(u);try{await o}catch{}}});return{promise:o,resolve:t,reject:a}}var no=y.createContext(null);no.displayName="DataRouter";var si=y.createContext(null);si.displayName="DataRouterState";var Ty=y.createContext(!1);function My(){return y.useContext(Ty)}var od=y.createContext({isTransitioning:!1});od.displayName="ViewTransition";var Dy=y.createContext(new Map);Dy.displayName="Fetchers";var LE=y.createContext(null);LE.displayName="Await";var gn=y.createContext(null);gn.displayName="Navigation";var Iu=y.createContext(null);Iu.displayName="Location";var Va=y.createContext({outlet:null,matches:[],isDataRoute:!1});Va.displayName="Route";var id=y.createContext(null);id.displayName="RouteError";var Oy="REACT_ROUTER_ERROR",jE="REDIRECT",FE="ROUTE_ERROR_RESPONSE";function kE(t){if(t.startsWith(`${Oy}:${jE}:{`))try{let a=JSON.parse(t.slice(28));if(typeof a=="object"&&a&&typeof a.status=="number"&&typeof a.statusText=="string"&&typeof a.location=="string"&&typeof a.reloadDocument=="boolean"&&typeof a.replace=="boolean")return a}catch{}}function zE(t){if(t.startsWith(`${Oy}:${FE}:{`))try{let a=JSON.parse(t.slice(40));if(typeof a=="object"&&a&&typeof a.status=="number"&&typeof a.statusText=="string")return new xl(a.status,a.statusText,a.data)}catch{}}function UE(t,{relative:a}={}){Ie(ui(),"useHref() may be used only in the context of a <Router> component.");let{basename:o,navigator:i}=y.useContext(gn),{hash:s,pathname:u,search:c}=_l(t,{relative:a}),d=u;return o!=="/"&&(d=u==="/"?o:na([o,u])),i.createHref({pathname:d,search:c,hash:s})}function ui(){return y.useContext(Iu)!=null}function ft(){return Ie(ui(),"useLocation() may be used only in the context of a <Router> component."),y.useContext(Iu).location}function PE(t){Ie(ui(),"useMatch() may be used only in the context of a <Router> component.");let{pathname:a}=ft();return y.useMemo(()=>Zr(t,cy(a)),[a,t])}var Ny="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function Ly(t){y.useContext(gn).static||y.useLayoutEffect(t)}function ld(){let{isDataRoute:t}=y.useContext(Va);return t?JE():IE()}function IE(){Ie(ui(),"useNavigate() may be used only in the context of a <Router> component.");let t=y.useContext(no),{basename:a,navigator:o}=y.useContext(gn),{matches:i}=y.useContext(Va),{pathname:s}=ft(),u=JSON.stringify(td(i)),c=y.useRef(!1);return Ly(()=>{c.current=!0}),y.useCallback((v,m={})=>{if(Dt(c.current,Ny),!c.current)return;if(typeof v=="number"){o.go(v);return}let A=Pu(v,JSON.parse(u),s,m.relative==="path");t==null&&a!=="/"&&(A.pathname=A.pathname==="/"?a:na([a,A.pathname])),(m.replace?o.replace:o.push)(A,m.state,m)},[a,o,u,s,t])}y.createContext(null);function _l(t,{relative:a}={}){let{matches:o}=y.useContext(Va),{pathname:i}=ft(),s=JSON.stringify(td(o));return y.useMemo(()=>Pu(t,JSON.parse(s),i,a==="path"),[t,s,i,a])}function HE(t,a,o){Ie(ui(),"useRoutes() may be used only in the context of a <Router> component.");let{navigator:i}=y.useContext(gn),{matches:s}=y.useContext(Va),u=s[s.length-1],c=u?u.params:{},d=u?u.pathname:"/",v=u?u.pathnameBase:"/",m=u&&u.route;{let w=m&&m.path||"";ky(d,!m||w.endsWith("*")||w.endsWith("*?"),`You rendered descendant <Routes> (or called \`useRoutes()\`) at "${d}" (under <Route path="${w}">) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. |
|
| 12 | + | ||
| 13 | + | Please change the parent <Route path="${w}"> to <Route path="${w==="/"?"*":`${w}/*`}">.`)}let A=ft(),p;p=A;let C=p.pathname||"/",b=C;if(v!=="/"){let w=v.replace(/^\//,"").split("/");b="/"+C.replace(/^\//,"").split("/").slice(w.length).join("/")}let S=Ha(t,{pathname:b});return Dt(m||S!=null,`No routes matched location "${p.pathname}${p.search}${p.hash}" `),Dt(S==null||S[S.length-1].route.element!==void 0||S[S.length-1].route.Component!==void 0||S[S.length-1].route.lazy!==void 0,`Matched leaf route at location "${p.pathname}${p.search}${p.hash}" does not have an element or Component. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.`),GE(S&&S.map(w=>Object.assign({},w,{params:Object.assign({},c,w.params),pathname:na([v,i.encodeLocation?i.encodeLocation(w.pathname.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:w.pathname]),pathnameBase:w.pathnameBase==="/"?v:na([v,i.encodeLocation?i.encodeLocation(w.pathnameBase.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:w.pathnameBase])})),s,o)}function BE(){let t=ZE(),a=yl(t)?`${t.status} ${t.statusText}`:t instanceof Error?t.message:JSON.stringify(t),o=t instanceof Error?t.stack:null,i="rgba(200,200,200, 0.5)",s={padding:"0.5rem",backgroundColor:i},u={padding:"2px 4px",backgroundColor:i},c=null;return console.error("Error handled by React Router default ErrorBoundary:",t),c=y.createElement(y.Fragment,null,y.createElement("p",null,"💿 Hey developer 👋"),y.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",y.createElement("code",{style:u},"ErrorBoundary")," or"," ",y.createElement("code",{style:u},"errorElement")," prop on your route.")),y.createElement(y.Fragment,null,y.createElement("h2",null,"Unexpected Application Error!"),y.createElement("h3",{style:{fontStyle:"italic"}},a),o?y.createElement("pre",{style:s},o):null,c)}var $E=y.createElement(BE,null),jy=class extends y.Component{constructor(t){super(t),this.state={location:t.location,revalidation:t.revalidation,error:t.error}}static getDerivedStateFromError(t){return{error:t}}static getDerivedStateFromProps(t,a){return a.location!==t.location||a.revalidation!=="idle"&&t.revalidation==="idle"?{error:t.error,location:t.location,revalidation:t.revalidation}:{error:t.error!==void 0?t.error:a.error,location:a.location,revalidation:t.revalidation||a.revalidation}}componentDidCatch(t,a){this.props.onError?this.props.onError(t,a):console.error("React Router caught the following error during render",t)}render(){let t=this.state.error;if(this.context&&typeof t=="object"&&t&&"digest"in t&&typeof t.digest=="string"){const o=zE(t.digest);o&&(t=o)}let a=t!==void 0?y.createElement(Va.Provider,{value:this.props.routeContext},y.createElement(id.Provider,{value:t,children:this.props.component})):this.props.children;return this.context?y.createElement(VE,{error:t},a):a}};jy.contextType=Ty;var O2=new WeakMap;function VE({children:t,error:a}){let{basename:o}=y.useContext(gn);if(typeof a=="object"&&a&&"digest"in a&&typeof a.digest=="string"){let i=kE(a.digest);if(i){let s=O2.get(a);if(s)throw s;let u=py(i.location,o);if(hy&&!O2.get(a))if(u.isExternal||i.reloadDocument)window.location.href=u.absoluteURL||u.to;else{const c=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(u.to,{replace:i.replace}));throw O2.set(a,c),c}return y.createElement("meta",{httpEquiv:"refresh",content:`0;url=${u.absoluteURL||u.to}`})}}return t}function qE({routeContext:t,match:a,children:o}){let i=y.useContext(no);return i&&i.static&&i.staticContext&&(a.route.errorElement||a.route.ErrorBoundary)&&(i.staticContext._deepestRenderedBoundaryId=a.route.id),y.createElement(Va.Provider,{value:t},o)}function GE(t,a=[],o){let i=o?.state;if(t==null){if(!i)return null;if(i.errors)t=i.matches;else if(a.length===0&&!i.initialized&&i.matches.length>0)t=i.matches;else return null}let s=t,u=i?.errors;if(u!=null){let A=s.findIndex(p=>p.route.id&&u?.[p.route.id]!==void 0);Ie(A>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(u).join(",")}`),s=s.slice(0,Math.min(s.length,A+1))}let c=!1,d=-1;if(o&&i){c=i.renderFallback;for(let A=0;A<s.length;A++){let p=s[A];if((p.route.HydrateFallback||p.route.hydrateFallbackElement)&&(d=A),p.route.id){let{loaderData:C,errors:b}=i,S=p.route.loader&&!C.hasOwnProperty(p.route.id)&&(!b||b[p.route.id]===void 0);if(p.route.lazy||S){o.isStatic&&(c=!0),d>=0?s=s.slice(0,d+1):s=[s[0]];break}}}}let v=o?.onError,m=i&&v?(A,p)=>{v(A,{location:i.location,params:i.matches?.[0]?.params??{},unstable_pattern:wl(i.matches),errorInfo:p})}:void 0;return s.reduceRight((A,p,C)=>{let b,S=!1,x=null,w=null;i&&(b=u&&p.route.id?u[p.route.id]:void 0,x=p.route.errorElement||$E,c&&(d<0&&C===0?(ky("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),S=!0,w=null):d===C&&(S=!0,w=p.route.hydrateFallbackElement||null)));let D=a.concat(s.slice(0,C+1)),T=()=>{let R;return b?R=x:S?R=w:p.route.Component?R=y.createElement(p.route.Component,null):p.route.element?R=p.route.element:R=A,y.createElement(qE,{match:p,routeContext:{outlet:A,matches:D,isDataRoute:i!=null},children:R})};return i&&(p.route.ErrorBoundary||p.route.errorElement||C===0)?y.createElement(jy,{location:i.location,revalidation:i.revalidation,component:x,error:b,children:T(),routeContext:{outlet:null,matches:D,isDataRoute:!0},onError:m}):T()},null)}function sd(t){return`${t} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function YE(t){let a=y.useContext(no);return Ie(a,sd(t)),a}function ud(t){let a=y.useContext(si);return Ie(a,sd(t)),a}function QE(t){let a=y.useContext(Va);return Ie(a,sd(t)),a}function cd(t){let a=QE(t),o=a.matches[a.matches.length-1];return Ie(o.route.id,`${t} can only be used on routes that contain a unique "id"`),o.route.id}function KE(){return cd("useRouteId")}function XE(){return ud("useNavigation").navigation}function Fy(){let{matches:t,loaderData:a}=ud("useMatches");return y.useMemo(()=>t.map(o=>ly(o,a)),[t,a])}function ZE(){let t=y.useContext(id),a=ud("useRouteError"),o=cd("useRouteError");return t!==void 0?t:a.errors?.[o]}function JE(){let{router:t}=YE("useNavigate"),a=cd("useNavigate"),o=y.useRef(!1);return Ly(()=>{o.current=!0}),y.useCallback(async(s,u={})=>{Dt(o.current,Ny),o.current&&(typeof s=="number"?await t.navigate(s):await t.navigate(s,{fromRouteId:a,...u}))},[t,a])}var _g={};function ky(t,a,o){!a&&!_g[t]&&(_g[t]=!0,Dt(!1,o))}var Rg={};function Tg(t,a){!t&&!Rg[a]&&(Rg[a]=!0,console.warn(a))}var WE="useOptimistic",Mg=li[WE],e7=()=>{};function t7(t){return Mg?Mg(t):[t,e7]}function n7(t){let a={hasErrorBoundary:t.hasErrorBoundary||t.ErrorBoundary!=null||t.errorElement!=null};return t.Component&&(t.element&&Dt(!1,"You should not include both `Component` and `element` on your route - `Component` will be used."),Object.assign(a,{element:y.createElement(t.Component),Component:void 0})),t.HydrateFallback&&(t.hydrateFallbackElement&&Dt(!1,"You should not include both `HydrateFallback` and `hydrateFallbackElement` on your route - `HydrateFallback` will be used."),Object.assign(a,{hydrateFallbackElement:y.createElement(t.HydrateFallback),HydrateFallback:void 0})),t.ErrorBoundary&&(t.errorElement&&Dt(!1,"You should not include both `ErrorBoundary` and `errorElement` on your route - `ErrorBoundary` will be used."),Object.assign(a,{errorElement:y.createElement(t.ErrorBoundary),ErrorBoundary:void 0})),a}var a7=["HydrateFallback","hydrateFallbackElement"],r7=class{constructor(){this.status="pending",this.promise=new Promise((t,a)=>{this.resolve=o=>{this.status==="pending"&&(this.status="resolved",t(o))},this.reject=o=>{this.status==="pending"&&(this.status="rejected",a(o))}})}};function o7({router:t,flushSync:a,onError:o,unstable_useTransitions:i}){i=My()||i;let[u,c]=y.useState(t.state),[d,v]=t7(u),[m,A]=y.useState(),[p,C]=y.useState({isTransitioning:!1}),[b,S]=y.useState(),[x,w]=y.useState(),[D,T]=y.useState(),R=y.useRef(new Map),_=y.useCallback((O,{deletedFetchers:I,newErrors:re,flushSync:pe,viewTransitionOpts:ce})=>{re&&o&&Object.values(re).forEach(J=>o(J,{location:O.location,params:O.matches[0]?.params??{},unstable_pattern:wl(O.matches)})),O.fetchers.forEach((J,fe)=>{J.data!==void 0&&R.current.set(fe,J.data)}),I.forEach(J=>R.current.delete(J)),Tg(pe===!1||a!=null,'You provided the `flushSync` option to a router update, but you are not using the `<RouterProvider>` from `react-router/dom` so `ReactDOM.flushSync()` is unavailable. Please update your app to `import { RouterProvider } from "react-router/dom"` and ensure you have `react-dom` installed as a dependency to use the `flushSync` option.');let de=t.window!=null&&t.window.document!=null&&typeof t.window.document.startViewTransition=="function";if(Tg(ce==null||de,"You provided the `viewTransition` option to a router update, but you do not appear to be running in a DOM environment as `window.startViewTransition` is not available."),!ce||!de){a&&pe?a(()=>c(O)):i===!1?c(O):y.startTransition(()=>{i===!0&&v(J=>Dg(J,O)),c(O)});return}if(a&&pe){a(()=>{x&&(b?.resolve(),x.skipTransition()),C({isTransitioning:!0,flushSync:!0,currentLocation:ce.currentLocation,nextLocation:ce.nextLocation})});let J=t.window.document.startViewTransition(()=>{a(()=>c(O))});J.finished.finally(()=>{a(()=>{S(void 0),w(void 0),A(void 0),C({isTransitioning:!1})})}),a(()=>w(J));return}x?(b?.resolve(),x.skipTransition(),T({state:O,currentLocation:ce.currentLocation,nextLocation:ce.nextLocation})):(A(O),C({isTransitioning:!0,flushSync:!1,currentLocation:ce.currentLocation,nextLocation:ce.nextLocation}))},[t.window,a,x,b,i,v,o]);y.useLayoutEffect(()=>t.subscribe(_),[t,_]),y.useEffect(()=>{p.isTransitioning&&!p.flushSync&&S(new r7)},[p]),y.useEffect(()=>{if(b&&m&&t.window){let O=m,I=b.promise,re=t.window.document.startViewTransition(async()=>{i===!1?c(O):y.startTransition(()=>{i===!0&&v(pe=>Dg(pe,O)),c(O)}),await I});re.finished.finally(()=>{S(void 0),w(void 0),A(void 0),C({isTransitioning:!1})}),w(re)}},[m,b,t.window,i,v]),y.useEffect(()=>{b&&m&&d.location.key===m.location.key&&b.resolve()},[b,x,d.location,m]),y.useEffect(()=>{!p.isTransitioning&&D&&(A(D.state),C({isTransitioning:!0,flushSync:!1,currentLocation:D.currentLocation,nextLocation:D.nextLocation}),T(void 0))},[p.isTransitioning,D]);let N=y.useMemo(()=>({createHref:t.createHref,encodeLocation:t.encodeLocation,go:O=>t.navigate(O),push:(O,I,re)=>t.navigate(O,{state:I,preventScrollReset:re?.preventScrollReset}),replace:(O,I,re)=>t.navigate(O,{replace:!0,state:I,preventScrollReset:re?.preventScrollReset})}),[t]),j=t.basename||"/",F=y.useMemo(()=>({router:t,navigator:N,static:!1,basename:j,onError:o}),[t,N,j,o]);return y.createElement(y.Fragment,null,y.createElement(no.Provider,{value:F},y.createElement(si.Provider,{value:d},y.createElement(Dy.Provider,{value:R.current},y.createElement(od.Provider,{value:p},y.createElement(s7,{basename:j,location:d.location,navigationType:d.historyAction,navigator:N,unstable_useTransitions:i},y.createElement(i7,{routes:t.routes,future:t.future,state:d,isStatic:!1,onError:o})))))),null)}function Dg(t,a){return{...t,navigation:a.navigation.state!=="idle"?a.navigation:t.navigation,revalidation:a.revalidation!=="idle"?a.revalidation:t.revalidation,actionData:a.navigation.state!=="submitting"?a.actionData:t.actionData,fetchers:a.fetchers}}var i7=y.memo(l7);function l7({routes:t,future:a,state:o,isStatic:i,onError:s}){return HE(t,void 0,{state:o,isStatic:i,onError:s})}function s7({basename:t="/",children:a=null,location:o,navigationType:i="POP",navigator:s,static:u=!1,unstable_useTransitions:c}){Ie(!ui(),"You cannot render a <Router> inside another <Router>. You should never have more than one in your app.");let d=t.replace(/^\/*/,"/"),v=y.useMemo(()=>({basename:d,navigator:s,static:u,unstable_useTransitions:c,future:{}}),[d,s,u,c]);typeof o=="string"&&(o=Aa(o));let{pathname:m="/",search:A="",hash:p="",state:C=null,key:b="default",unstable_mask:S}=o,x=y.useMemo(()=>{let w=Dn(m,d);return w==null?null:{location:{pathname:w,search:A,hash:p,state:C,key:b,unstable_mask:S},navigationType:i}},[d,m,A,p,C,b,i,S]);return Dt(x!=null,`<Router basename="${d}"> is not able to match the URL "${m}${A}${p}" because it does not start with the basename, so the <Router> won't render anything.`),x==null?null:y.createElement(gn.Provider,{value:v},y.createElement(Iu.Provider,{children:a,value:x}))}var yu="get",Au="application/x-www-form-urlencoded";function Hu(t){return typeof HTMLElement<"u"&&t instanceof HTMLElement}function u7(t){return Hu(t)&&t.tagName.toLowerCase()==="button"}function c7(t){return Hu(t)&&t.tagName.toLowerCase()==="form"}function f7(t){return Hu(t)&&t.tagName.toLowerCase()==="input"}function d7(t){return!!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)}function h7(t,a){return t.button===0&&(!a||a==="_self")&&!d7(t)}var eu=null;function p7(){if(eu===null)try{new FormData(document.createElement("form"),0),eu=!1}catch{eu=!0}return eu}var m7=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function N2(t){return t!=null&&!m7.has(t)?(Dt(!1,`"${t}" is not a valid \`encType\` for \`<Form>\`/\`<fetcher.Form>\` and will default to "${Au}"`),null):t}function v7(t,a){let o,i,s,u,c;if(c7(t)){let d=t.getAttribute("action");i=d?Dn(d,a):null,o=t.getAttribute("method")||yu,s=N2(t.getAttribute("enctype"))||Au,u=new FormData(t)}else if(u7(t)||f7(t)&&(t.type==="submit"||t.type==="image")){let d=t.form;if(d==null)throw new Error('Cannot submit a <button> or <input type="submit"> without a <form>');let v=t.getAttribute("formaction")||d.getAttribute("action");if(i=v?Dn(v,a):null,o=t.getAttribute("formmethod")||d.getAttribute("method")||yu,s=N2(t.getAttribute("formenctype"))||N2(d.getAttribute("enctype"))||Au,u=new FormData(d,t),!p7()){let{name:m,type:A,value:p}=t;if(A==="image"){let C=m?`${m}.`:"";u.append(`${C}x`,"0"),u.append(`${C}y`,"0")}else m&&u.append(m,p)}}else{if(Hu(t))throw new Error('Cannot submit element that is not <form>, <button>, or <input type="submit|image">');o=yu,i=null,s=Au,c=t}return u&&s==="text/plain"&&(c=u,u=void 0),{action:i,method:o.toLowerCase(),encType:s,formData:u,body:c}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var g7={"&":"\\u0026",">":"\\u003e","<":"\\u003c","\u2028":"\\u2028","\u2029":"\\u2029"},y7=/[&><\u2028\u2029]/g;function Og(t){return t.replace(y7,a=>g7[a])}function fd(t,a){if(t===!1||t===null||typeof t>"u")throw new Error(a)}function zy(t,a,o,i){let s=typeof t=="string"?new URL(t,typeof window>"u"?"server://singlefetch/":window.location.origin):t;return o?s.pathname.endsWith("/")?s.pathname=`${s.pathname}_.${i}`:s.pathname=`${s.pathname}.${i}`:s.pathname==="/"?s.pathname=`_root.${i}`:a&&Dn(s.pathname,a)==="/"?s.pathname=`${a.replace(/\/$/,"")}/_root.${i}`:s.pathname=`${s.pathname.replace(/\/$/,"")}.${i}`,s}async function A7(t,a){if(t.id in a)return a[t.id];try{let o=await import(t.module);return a[t.id]=o,o}catch(o){return console.error(`Error loading route module \`${t.module}\`, reloading page...`),console.error(o),window.__reactRouterContext&&window.__reactRouterContext.isSpaMode,window.location.reload(),new Promise(()=>{})}}function C7(t){return t==null?!1:t.href==null?t.rel==="preload"&&typeof t.imageSrcSet=="string"&&typeof t.imageSizes=="string":typeof t.rel=="string"&&typeof t.href=="string"}async function b7(t,a,o){let i=await Promise.all(t.map(async s=>{let u=a.routes[s.route.id];if(u){let c=await A7(u,o);return c.links?c.links():[]}return[]}));return w7(i.flat(1).filter(C7).filter(s=>s.rel==="stylesheet"||s.rel==="preload").map(s=>s.rel==="stylesheet"?{...s,rel:"prefetch",as:"style"}:{...s,rel:"prefetch"}))}function Ng(t,a,o,i,s,u){let c=(v,m)=>o[m]?v.route.id!==o[m].route.id:!0,d=(v,m)=>o[m].pathname!==v.pathname||o[m].route.path?.endsWith("*")&&o[m].params["*"]!==v.params["*"];return u==="assets"?a.filter((v,m)=>c(v,m)||d(v,m)):u==="data"?a.filter((v,m)=>{let A=i.routes[v.route.id];if(!A||!A.hasLoader)return!1;if(c(v,m)||d(v,m))return!0;if(v.route.shouldRevalidate){let p=v.route.shouldRevalidate({currentUrl:new URL(s.pathname+s.search+s.hash,window.origin),currentParams:o[0]?.params||{},nextUrl:new URL(t,window.origin),nextParams:v.params,defaultShouldRevalidate:!0});if(typeof p=="boolean")return p}return!0}):[]}function E7(t,a,{includeHydrateFallback:o}={}){return S7(t.map(i=>{let s=a.routes[i.route.id];if(!s)return[];let u=[s.module];return s.clientActionModule&&(u=u.concat(s.clientActionModule)),s.clientLoaderModule&&(u=u.concat(s.clientLoaderModule)),o&&s.hydrateFallbackModule&&(u=u.concat(s.hydrateFallbackModule)),s.imports&&(u=u.concat(s.imports)),u}).flat(1))}function S7(t){return[...new Set(t)]}function x7(t){let a={},o=Object.keys(t).sort();for(let i of o)a[i]=t[i];return a}function w7(t,a){let o=new Set;return new Set(a),t.reduce((i,s)=>{let u=JSON.stringify(x7(s));return o.has(u)||(o.add(u),i.push({key:u,link:s})),i},[])}function dd(){let t=y.useContext(no);return fd(t,"You must render this element inside a <DataRouterContext.Provider> element"),t}function _7(){let t=y.useContext(si);return fd(t,"You must render this element inside a <DataRouterStateContext.Provider> element"),t}var Bu=y.createContext(void 0);Bu.displayName="FrameworkContext";function hd(){let t=y.useContext(Bu);return fd(t,"You must render this element inside a <HydratedRouter> element"),t}function R7(t,a){let o=y.useContext(Bu),[i,s]=y.useState(!1),[u,c]=y.useState(!1),{onFocus:d,onBlur:v,onMouseEnter:m,onMouseLeave:A,onTouchStart:p}=a,C=y.useRef(null);y.useEffect(()=>{if(t==="render"&&c(!0),t==="viewport"){let x=D=>{D.forEach(T=>{c(T.isIntersecting)})},w=new IntersectionObserver(x,{threshold:.5});return C.current&&w.observe(C.current),()=>{w.disconnect()}}},[t]),y.useEffect(()=>{if(i){let x=setTimeout(()=>{c(!0)},100);return()=>{clearTimeout(x)}}},[i]);let b=()=>{s(!0)},S=()=>{s(!1),c(!1)};return o?t!=="intent"?[u,C,{}]:[u,C,{onFocus:ll(d,b),onBlur:ll(v,S),onMouseEnter:ll(m,b),onMouseLeave:ll(A,S),onTouchStart:ll(p,b)}]:[!1,C,{}]}function ll(t,a){return o=>{t&&t(o),o.defaultPrevented||a(o)}}function T7({page:t,...a}){let o=My(),{router:i}=dd(),s=y.useMemo(()=>Ha(i.routes,t,i.basename),[i.routes,t,i.basename]);return s?o?y.createElement(D7,{page:t,matches:s,...a}):y.createElement(O7,{page:t,matches:s,...a}):null}function M7(t){let{manifest:a,routeModules:o}=hd(),[i,s]=y.useState([]);return y.useEffect(()=>{let u=!1;return b7(t,a,o).then(c=>{u||s(c)}),()=>{u=!0}},[t,a,o]),i}function D7({page:t,matches:a,...o}){let i=ft(),{future:s}=hd(),{basename:u}=dd(),c=y.useMemo(()=>{if(t===i.pathname+i.search+i.hash)return[];let d=zy(t,u,s.unstable_trailingSlashAwareDataRequests,"rsc"),v=!1,m=[];for(let A of a)typeof A.route.shouldRevalidate=="function"?v=!0:m.push(A.route.id);return v&&m.length>0&&d.searchParams.set("_routes",m.join(",")),[d.pathname+d.search]},[u,s.unstable_trailingSlashAwareDataRequests,t,i,a]);return y.createElement(y.Fragment,null,c.map(d=>y.createElement("link",{key:d,rel:"prefetch",as:"fetch",href:d,...o})))}function O7({page:t,matches:a,...o}){let i=ft(),{future:s,manifest:u,routeModules:c}=hd(),{basename:d}=dd(),{loaderData:v,matches:m}=_7(),A=y.useMemo(()=>Ng(t,a,m,u,i,"data"),[t,a,m,u,i]),p=y.useMemo(()=>Ng(t,a,m,u,i,"assets"),[t,a,m,u,i]),C=y.useMemo(()=>{if(t===i.pathname+i.search+i.hash)return[];let x=new Set,w=!1;if(a.forEach(T=>{let R=u.routes[T.route.id];!R||!R.hasLoader||(!A.some(_=>_.route.id===T.route.id)&&T.route.id in v&&c[T.route.id]?.shouldRevalidate||R.hasClientLoader?w=!0:x.add(T.route.id))}),x.size===0)return[];let D=zy(t,d,s.unstable_trailingSlashAwareDataRequests,"data");return w&&x.size>0&&D.searchParams.set("_routes",a.filter(T=>x.has(T.route.id)).map(T=>T.route.id).join(",")),[D.pathname+D.search]},[d,s.unstable_trailingSlashAwareDataRequests,v,i,u,A,a,t,c]),b=y.useMemo(()=>E7(p,u),[p,u]),S=M7(p);return y.createElement(y.Fragment,null,C.map(x=>y.createElement("link",{key:x,rel:"prefetch",as:"fetch",href:x,...o})),b.map(x=>y.createElement("link",{key:x,rel:"modulepreload",href:x,...o})),S.map(({key:x,link:w})=>y.createElement("link",{key:x,nonce:o.nonce,...w,crossOrigin:w.crossOrigin??o.crossOrigin})))}function N7(...t){return a=>{t.forEach(o=>{typeof o=="function"?o(a):o!=null&&(o.current=a)})}}var L7=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";try{L7&&(window.__reactRouterVersion="7.14.0")}catch{}function j7(t,a){return sE({basename:a?.basename,getContext:a?.getContext,future:a?.future,history:_b({window:a?.window}),hydrationData:a?.hydrationData||F7(),routes:t,mapRouteProperties:n7,hydrationRouteProperties:a7,dataStrategy:a?.dataStrategy,patchRoutesOnNavigation:a?.patchRoutesOnNavigation,window:a?.window,unstable_instrumentations:a?.unstable_instrumentations}).initialize()}function F7(){let t=window?.__staticRouterHydrationData;return t&&t.errors&&(t={...t,errors:k7(t.errors)}),t}function k7(t){if(!t)return null;let a=Object.entries(t),o={};for(let[i,s]of a)if(s&&s.__type==="RouteErrorResponse")o[i]=new xl(s.status,s.statusText,s.data,s.internal===!0);else if(s&&s.__type==="Error"){if(s.__subType){let u=window[s.__subType];if(typeof u=="function")try{let c=new u(s.message);c.stack="",o[i]=c}catch{}}if(o[i]==null){let u=new Error(s.message);u.stack="",o[i]=u}}else o[i]=s;return o}var Uy=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,ci=y.forwardRef(function({onClick:a,discover:o="render",prefetch:i="none",relative:s,reloadDocument:u,replace:c,unstable_mask:d,state:v,target:m,to:A,preventScrollReset:p,viewTransition:C,unstable_defaultShouldRevalidate:b,...S},x){let{basename:w,navigator:D,unstable_useTransitions:T}=y.useContext(gn),R=typeof A=="string"&&Uy.test(A),_=py(A,w);A=_.to;let N=UE(A,{relative:s}),j=ft(),F=null;if(d){let fe=Pu(d,[],j.unstable_mask?j.unstable_mask.pathname:"/",!0);w!=="/"&&(fe.pathname=fe.pathname==="/"?w:na([w,fe.pathname])),F=D.createHref(fe)}let[O,I,re]=R7(i,S),pe=I7(A,{replace:c,unstable_mask:d,state:v,target:m,preventScrollReset:p,relative:s,viewTransition:C,unstable_defaultShouldRevalidate:b,unstable_useTransitions:T});function ce(fe){a&&a(fe),fe.defaultPrevented||pe(fe)}let de=!(_.isExternal||u),J=y.createElement("a",{...S,...re,href:(de?F:void 0)||_.absoluteURL||N,onClick:de?ce:a,ref:N7(x,I),target:m,"data-discover":!R&&o==="render"?"true":void 0});return O&&!R?y.createElement(y.Fragment,null,J,y.createElement(T7,{page:N})):J});ci.displayName="Link";var z7=y.forwardRef(function({"aria-current":a="page",caseSensitive:o=!1,className:i="",end:s=!1,style:u,to:c,viewTransition:d,children:v,...m},A){let p=_l(c,{relative:m.relative}),C=ft(),b=y.useContext(si),{navigator:S,basename:x}=y.useContext(gn),w=b!=null&&Y7(p)&&d===!0,D=S.encodeLocation?S.encodeLocation(p).pathname:p.pathname,T=C.pathname,R=b&&b.navigation&&b.navigation.location?b.navigation.location.pathname:null;o||(T=T.toLowerCase(),R=R?R.toLowerCase():null,D=D.toLowerCase()),R&&x&&(R=Dn(R,x)||R);const _=D!=="/"&&D.endsWith("/")?D.length-1:D.length;let N=T===D||!s&&T.startsWith(D)&&T.charAt(_)==="/",j=R!=null&&(R===D||!s&&R.startsWith(D)&&R.charAt(D.length)==="/"),F={isActive:N,isPending:j,isTransitioning:w},O=N?a:void 0,I;typeof i=="function"?I=i(F):I=[i,N?"active":null,j?"pending":null,w?"transitioning":null].filter(Boolean).join(" ");let re=typeof u=="function"?u(F):u;return y.createElement(ci,{...m,"aria-current":O,className:I,ref:A,style:re,to:c,viewTransition:d},typeof v=="function"?v(F):v)});z7.displayName="NavLink";var U7=y.forwardRef(({discover:t="render",fetcherKey:a,navigate:o,reloadDocument:i,replace:s,state:u,method:c=yu,action:d,onSubmit:v,relative:m,preventScrollReset:A,viewTransition:p,unstable_defaultShouldRevalidate:C,...b},S)=>{let{unstable_useTransitions:x}=y.useContext(gn),w=$7(),D=V7(d,{relative:m}),T=c.toLowerCase()==="get"?"get":"post",R=typeof d=="string"&&Uy.test(d),_=N=>{if(v&&v(N),N.defaultPrevented)return;N.preventDefault();let j=N.nativeEvent.submitter,F=j?.getAttribute("formmethod")||c,O=()=>w(j||N.currentTarget,{fetcherKey:a,method:F,navigate:o,replace:s,state:u,relative:m,preventScrollReset:A,viewTransition:p,unstable_defaultShouldRevalidate:C});x&&o!==!1?y.startTransition(()=>O()):O()};return y.createElement("form",{ref:S,method:T,action:D,onSubmit:i?v:_,...b,"data-discover":!R&&t==="render"?"true":void 0})});U7.displayName="Form";function Py({getKey:t,storageKey:a,...o}){let i=y.useContext(Bu),{basename:s}=y.useContext(gn),u=ft(),c=Fy();q7({getKey:t,storageKey:a});let d=y.useMemo(()=>{if(!i||!t)return null;let m=xf(u,c,s,t);return m!==u.key?m:null},[]);if(!i||i.isSpaMode)return null;let v=((m,A)=>{if(!window.history.state||!window.history.state.key){let p=Math.random().toString(32).slice(2);window.history.replaceState({key:p},"")}try{let C=JSON.parse(sessionStorage.getItem(m)||"{}")[A||window.history.state.key];typeof C=="number"&&window.scrollTo(0,C)}catch(p){console.error(p),sessionStorage.removeItem(m)}}).toString();return y.createElement("script",{...o,suppressHydrationWarning:!0,dangerouslySetInnerHTML:{__html:`(${v})(${Og(JSON.stringify(a||Sf))}, ${Og(JSON.stringify(d))})`}})}Py.displayName="ScrollRestoration";function Iy(t){return`${t} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function pd(t){let a=y.useContext(no);return Ie(a,Iy(t)),a}function P7(t){let a=y.useContext(si);return Ie(a,Iy(t)),a}function I7(t,{target:a,replace:o,unstable_mask:i,state:s,preventScrollReset:u,relative:c,viewTransition:d,unstable_defaultShouldRevalidate:v,unstable_useTransitions:m}={}){let A=ld(),p=ft(),C=_l(t,{relative:c});return y.useCallback(b=>{if(h7(b,a)){b.preventDefault();let S=o!==void 0?o:ya(p)===ya(C),x=()=>A(t,{replace:S,unstable_mask:i,state:s,preventScrollReset:u,relative:c,viewTransition:d,unstable_defaultShouldRevalidate:v});m?y.startTransition(()=>x()):x()}},[p,A,C,o,i,s,a,t,u,c,d,v,m])}var H7=0,B7=()=>`__${String(++H7)}__`;function $7(){let{router:t}=pd("useSubmit"),{basename:a}=y.useContext(gn),o=KE(),i=t.fetch,s=t.navigate;return y.useCallback(async(u,c={})=>{let{action:d,method:v,encType:m,formData:A,body:p}=v7(u,a);if(c.navigate===!1){let C=c.fetcherKey||B7();await i(C,o,c.action||d,{unstable_defaultShouldRevalidate:c.unstable_defaultShouldRevalidate,preventScrollReset:c.preventScrollReset,formData:A,body:p,formMethod:c.method||v,formEncType:c.encType||m,flushSync:c.flushSync})}else await s(c.action||d,{unstable_defaultShouldRevalidate:c.unstable_defaultShouldRevalidate,preventScrollReset:c.preventScrollReset,formData:A,body:p,formMethod:c.method||v,formEncType:c.encType||m,replace:c.replace,state:c.state,fromRouteId:o,flushSync:c.flushSync,viewTransition:c.viewTransition})},[i,s,a,o])}function V7(t,{relative:a}={}){let{basename:o}=y.useContext(gn),i=y.useContext(Va);Ie(i,"useFormAction must be used inside a RouteContext");let[s]=i.matches.slice(-1),u={..._l(t||".",{relative:a})},c=ft();if(t==null){u.search=c.search;let d=new URLSearchParams(u.search),v=d.getAll("index");if(v.some(A=>A==="")){d.delete("index"),v.filter(p=>p).forEach(p=>d.append("index",p));let A=d.toString();u.search=A?`?${A}`:""}}return(!t||t===".")&&s.route.index&&(u.search=u.search?u.search.replace(/^\?/,"?index&"):"?index"),o!=="/"&&(u.pathname=u.pathname==="/"?o:na([o,u.pathname])),ya(u)}var Sf="react-router-scroll-positions",tu={};function xf(t,a,o,i){let s=null;return i&&(o!=="/"?s=i({...t,pathname:Dn(t.pathname,o)||t.pathname},a):s=i(t,a)),s==null&&(s=t.key),s}function q7({getKey:t,storageKey:a}={}){let{router:o}=pd("useScrollRestoration"),{restoreScrollPosition:i,preventScrollReset:s}=P7("useScrollRestoration"),{basename:u}=y.useContext(gn),c=ft(),d=Fy(),v=XE();y.useEffect(()=>(window.history.scrollRestoration="manual",()=>{window.history.scrollRestoration="auto"}),[]),G7(y.useCallback(()=>{if(v.state==="idle"){let m=xf(c,d,u,t);tu[m]=window.scrollY}try{sessionStorage.setItem(a||Sf,JSON.stringify(tu))}catch(m){Dt(!1,`Failed to save scroll positions in sessionStorage, <ScrollRestoration /> will not work properly (${m}).`)}window.history.scrollRestoration="auto"},[v.state,t,u,c,d,a])),typeof document<"u"&&(y.useLayoutEffect(()=>{try{let m=sessionStorage.getItem(a||Sf);m&&(tu=JSON.parse(m))}catch{}},[a]),y.useLayoutEffect(()=>{let m=o?.enableScrollRestoration(tu,()=>window.scrollY,t?(A,p)=>xf(A,p,u,t):void 0);return()=>m&&m()},[o,u,t]),y.useLayoutEffect(()=>{if(i!==!1){if(typeof i=="number"){window.scrollTo(0,i);return}try{if(c.hash){let m=document.getElementById(decodeURIComponent(c.hash.slice(1)));if(m){m.scrollIntoView();return}}}catch{Dt(!1,`"${c.hash.slice(1)}" is not a decodable element ID. The view will not scroll to it.`)}s!==!0&&window.scrollTo(0,0)}},[c,i,s]))}function G7(t,a){let{capture:o}={};y.useEffect(()=>{let i=o!=null?{capture:o}:void 0;return window.addEventListener("pagehide",t,i),()=>{window.removeEventListener("pagehide",t,i)}},[t,o])}function Y7(t,{relative:a}={}){let o=y.useContext(od);Ie(o!=null,"`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?");let{basename:i}=pd("useViewTransitionState"),s=_l(t,{relative:a});if(!o.isTransitioning)return!1;let u=Dn(o.currentLocation.pathname,i)||o.currentLocation.pathname,c=Dn(o.nextLocation.pathname,i)||o.nextLocation.pathname;return Zr(s.pathname,c)!=null||Zr(s.pathname,u)!=null}function wf(t){return Array.isArray(t)?t.map(wf):typeof t=="object"&&t!==null?Object.keys(t).reduce((a,o)=>(a[o]=wf(t[o]),a),{}):typeof t=="string"&&t.includes("_vocs-fn_")?new Function(`return ${t.slice(9)}`)():t}const Hy=wf({aiCta:!0,blogDir:"./pages/blog",checkDeadlinks:!0,rootDir:"docs",title:"Andromeda",titleTemplate:"%s – Andromeda",markdown:{code:{themes:{light:"github-dark-high-contrast",dark:"github-dark-high-contrast"}}},theme:{colorScheme:"dark",accentColor:{backgroundAccent:{dark:"#FFB757",light:"#FFB757"},backgroundAccentHover:{dark:"#f1ab4b",light:"#f1ab4b"},backgroundAccentText:{dark:"black",light:"black"},borderAccent:{dark:"#ffd06f",light:"#f1ab4b"},textAccent:{dark:"#FFB757",light:"#FFB757"},textAccentHover:{dark:"#e39f3f",light:"#e39f3f"}}},sidebar:[{text:"Intro",items:[{text:"Quickstart",link:"/quickstart"},{text:"What is Andromeda",link:"/what-is-andromeda"}]},{text:"Apps",items:[{text:"Feeds",link:"/apps/feeds"},{text:"Jotts",link:"/apps/jotts"},{text:"Sipp",link:"/apps/sipp"},{text:"OG",link:"/apps/og"},{text:"Shrink",link:"/apps/shrink"},{text:"Parcels",link:"/apps/parcels"}]},{text:"DIY",items:[{text:"Stack",link:"/diy/stack"},{text:"Skills",link:"/diy/skills"}]}],basePath:"",font:{},socials:[],topNav:[],vite:{}}),Q7="modulepreload",K7=function(t){return"/"+t},Lg={},Ft=function(a,o,i){let s=Promise.resolve();if(o&&o.length>0){let v=function(m){return Promise.all(m.map(A=>Promise.resolve(A).then(p=>({status:"fulfilled",value:p}),p=>({status:"rejected",reason:p}))))};document.getElementsByTagName("link");const c=document.querySelector("meta[property=csp-nonce]"),d=c?.nonce||c?.getAttribute("nonce");s=v(o.map(m=>{if(m=K7(m),m in Lg)return;Lg[m]=!0;const A=m.endsWith(".css"),p=A?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${m}"]${p}`))return;const C=document.createElement("link");if(C.rel=A?"stylesheet":Q7,A||(C.as="script"),C.crossOrigin="",C.href=m,d&&C.setAttribute("nonce",d),document.head.appendChild(C),A)return new Promise((b,S)=>{C.addEventListener("load",b),C.addEventListener("error",()=>S(new Error(`Unable to preload CSS for ${m}`)))})}))}function u(c){const d=new Event("vite:preloadError",{cancelable:!0});if(d.payload=c,window.dispatchEvent(d),!d.defaultPrevented)throw c}return s.then(c=>{for(const d of c||[])d.status==="rejected"&&u(d.reason);return a().catch(u)})},By=y.createContext(Hy);function $y(){return Hy}function X7({children:t,config:a}){const[o,i]=y.useState(()=>a||$y());return y.useEffect(()=>{},[]),y.useEffect(()=>{},[o]),g.jsx(By.Provider,{value:o,children:t})}function Ot(){return y.useContext(By)}const md=[{lazy:()=>Ft(()=>import("./index-OhQ8uz5Z.js"),[]),path:"/",type:"mdx",filePath:"index.mdx",content:"---%0Alayout%3A%20landing%0Acontent%3A%0A%20%20horizontalPadding%3A%200px%0A%20%20width%3A%20100%25%0A%20%20verticalPadding%3A%200px%0A---%0A%0Aimport%20%7B%20Landing%20%7D%20from%20%22..%2Fcomponents%2FLanding%22%0Aimport%20%22..%2Flanding.css%22%0A%0A%3CLanding%20%2F%3E%0A%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./quickstart-DWI_ZLlc.js"),[]),path:"/quickstart",type:"mdx",filePath:"quickstart.mdx",content:"%23%20Quickstart%0A%0AGet%20up%20and%20running%20with%20any%20Andromeda%20app%20in%20minutes.%0A%0A%23%23%20Prerequisites%0A%0AMake%20sure%20%5BRust%5D(https%3A%2F%2Fwww.rust-lang.org%2Ftools%2Finstall)%20is%20installed%3A%0A%0A%60%60%60bash%0Arustc%20--version%0A%60%60%60%0A%0A%23%23%20Clone%20the%20Workspace%0A%0A%60%60%60bash%0Agit%20clone%20https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fandromeda.git%0Acd%20andromeda%0A%60%60%60%0A%0A%23%23%20Build%20All%20Apps%0A%0A%60%60%60bash%0Acargo%20build%20--release%0A%60%60%60%0A%0A%23%23%20Run%20a%20Specific%20App%0A%0AEach%20app%20is%20a%20workspace%20member.%20Run%20any%20of%20them%20with%20%60cargo%20run%20-p%60%3A%0A%0A%60%60%60bash%0Acargo%20run%20-p%20sipp%20--%20server%20--port%203000%0Acargo%20run%20-p%20feeds%0Acargo%20run%20-p%20parcels%0Acargo%20run%20-p%20jotts%0Acargo%20run%20-p%20og%0Acargo%20run%20-p%20shrink%0A%60%60%60%0A%0AMost%20apps%20start%20on%20%60http%3A%2F%2Flocalhost%3A3000%60%20by%20default.%20Check%20each%20app's%20page%20for%20specific%20environment%20variables%20and%20configuration.%0A%0A%23%23%20Environment%20Variables%0A%0AMost%20apps%20use%20a%20%60.env%60%20file%20for%20configuration.%20Copy%20the%20example%20file%20and%20fill%20in%20your%20values%3A%0A%0A%60%60%60bash%0Acp%20apps%2F%3Capp-name%3E%2F.env.example%20.env%0A%60%60%60%0A%0A%23%23%20Deployment%0A%0AEvery%20app%20compiles%20to%20a%20single%20binary%20with%20embedded%20assets%2C%20making%20deployment%20straightforward.%20Each%20app%20supports%3A%0A%0A-%20**Railway**%20-%20one-click%20deploy%20buttons%20on%20each%20app's%20page%0A-%20**Docker**%20-%20%60docker%20compose%20up%20-d%60%0A-%20**Binary**%20-%20copy%20the%20binary%20to%20your%20server%20and%20run%20it%20directly%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./quickstart-DWI_ZLlc.js"),[]),path:"/quickstart.html",type:"mdx",filePath:"quickstart.mdx",content:"%23%20Quickstart%0A%0AGet%20up%20and%20running%20with%20any%20Andromeda%20app%20in%20minutes.%0A%0A%23%23%20Prerequisites%0A%0AMake%20sure%20%5BRust%5D(https%3A%2F%2Fwww.rust-lang.org%2Ftools%2Finstall)%20is%20installed%3A%0A%0A%60%60%60bash%0Arustc%20--version%0A%60%60%60%0A%0A%23%23%20Clone%20the%20Workspace%0A%0A%60%60%60bash%0Agit%20clone%20https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fandromeda.git%0Acd%20andromeda%0A%60%60%60%0A%0A%23%23%20Build%20All%20Apps%0A%0A%60%60%60bash%0Acargo%20build%20--release%0A%60%60%60%0A%0A%23%23%20Run%20a%20Specific%20App%0A%0AEach%20app%20is%20a%20workspace%20member.%20Run%20any%20of%20them%20with%20%60cargo%20run%20-p%60%3A%0A%0A%60%60%60bash%0Acargo%20run%20-p%20sipp%20--%20server%20--port%203000%0Acargo%20run%20-p%20feeds%0Acargo%20run%20-p%20parcels%0Acargo%20run%20-p%20jotts%0Acargo%20run%20-p%20og%0Acargo%20run%20-p%20shrink%0A%60%60%60%0A%0AMost%20apps%20start%20on%20%60http%3A%2F%2Flocalhost%3A3000%60%20by%20default.%20Check%20each%20app's%20page%20for%20specific%20environment%20variables%20and%20configuration.%0A%0A%23%23%20Environment%20Variables%0A%0AMost%20apps%20use%20a%20%60.env%60%20file%20for%20configuration.%20Copy%20the%20example%20file%20and%20fill%20in%20your%20values%3A%0A%0A%60%60%60bash%0Acp%20apps%2F%3Capp-name%3E%2F.env.example%20.env%0A%60%60%60%0A%0A%23%23%20Deployment%0A%0AEvery%20app%20compiles%20to%20a%20single%20binary%20with%20embedded%20assets%2C%20making%20deployment%20straightforward.%20Each%20app%20supports%3A%0A%0A-%20**Railway**%20-%20one-click%20deploy%20buttons%20on%20each%20app's%20page%0A-%20**Docker**%20-%20%60docker%20compose%20up%20-d%60%0A-%20**Binary**%20-%20copy%20the%20binary%20to%20your%20server%20and%20run%20it%20directly%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./what-is-andromeda-CLSLj04f.js"),[]),path:"/what-is-andromeda",type:"mdx",filePath:"what-is-andromeda.mdx",content:"%23%20What%20is%20Andromeda%0A%0AAndromeda%20is%20a%20Rust%20workspace%20of%20minimal%2C%20self-hosted%20web%20apps.%20Each%20app%20compiles%20to%20a%20single%20binary%20powered%20by%20%5BAxum%5D(https%3A%2F%2Fgithub.com%2Ftokio-rs%2Faxum)%2C%20%5BSQLite%5D(https%3A%2F%2Fgithub.com%2Frusqlite%2Frusqlite)%2C%20and%20%5BAskama%5D(https%3A%2F%2Fgithub.com%2Fdjc%2Faskama)%20templates.%0A%0A%23%23%20Philosophy%0A%0AEvery%20app%20in%20Andromeda%20follows%20the%20same%20principles%3A%0A%0A-%20**Single%20binary**%20-%20Each%20app%20compiles%20to%20one%20small%20binary%20(~7MB)%20with%20all%20assets%20embedded%20at%20compile%20time%0A-%20**Minimal%20resource%20usage**%20-%20Apps%20average%20around%20~10MB%20of%20RAM%0A-%20**Self-hosted**%20-%20You%20own%20your%20data%20and%20run%20it%20on%20your%20own%20infrastructure%0A-%20**Simple%20deployment**%20-%20One%20binary%2C%20one%20optional%20%60.env%60%20file%2C%20no%20external%20dependencies%0A-%20**Consistent%20stack**%20-%20All%20apps%20share%20the%20same%20Rust%20stack%20so%20patterns%20are%20transferable%0A%0A%23%23%20Apps%0A%0A%7C%20App%20%7C%20Description%20%7C%0A%7C---%7C---%7C%0A%7C%20%5BSipp%5D(%2Fapps%2Fsipp)%20%7C%20Code%20sharing%20with%20web%20UI%20and%20TUI%20%7C%0A%7C%20%5BFeeds%5D(%2Fapps%2Ffeeds)%20%7C%20RSS%20reader%20with%20FreshRSS%20and%20OPML%20support%20%7C%0A%7C%20%5BParcels%5D(%2Fapps%2Fparcels)%20%7C%20Package%20tracking%20(USPS)%20%7C%0A%7C%20%5BJotts%5D(%2Fapps%2Fjotts)%20%7C%20Markdown%20notes%20%7C%0A%7C%20%5BOG%5D(%2Fapps%2Fog)%20%7C%20Open%20Graph%20tag%20inspector%20%7C%0A%7C%20%5BShrink%5D(%2Fapps%2Fshrink)%20%7C%20Image%20compression%20and%20resizing%20%7C%0A%0A%23%23%20Shared%20Crates%0A%0A%7C%20Crate%20%7C%20Description%20%7C%0A%7C---%7C---%7C%0A%7C%20%60andromeda-auth%60%20%7C%20Session-based%20password%20authentication%20%7C%0A%0AThe%20%60andromeda-auth%60%20crate%20provides%20a%20shared%20authentication%20layer%20used%20across%20apps%20that%20require%20login%2C%20including%20session%20cookies%20and%20constant-time%20password%20verification.%0A%0A%23%23%20License%0A%0A%5BMIT%5D(https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fandromeda%2Fblob%2Fmain%2FLICENSE)%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./what-is-andromeda-CLSLj04f.js"),[]),path:"/what-is-andromeda.html",type:"mdx",filePath:"what-is-andromeda.mdx",content:"%23%20What%20is%20Andromeda%0A%0AAndromeda%20is%20a%20Rust%20workspace%20of%20minimal%2C%20self-hosted%20web%20apps.%20Each%20app%20compiles%20to%20a%20single%20binary%20powered%20by%20%5BAxum%5D(https%3A%2F%2Fgithub.com%2Ftokio-rs%2Faxum)%2C%20%5BSQLite%5D(https%3A%2F%2Fgithub.com%2Frusqlite%2Frusqlite)%2C%20and%20%5BAskama%5D(https%3A%2F%2Fgithub.com%2Fdjc%2Faskama)%20templates.%0A%0A%23%23%20Philosophy%0A%0AEvery%20app%20in%20Andromeda%20follows%20the%20same%20principles%3A%0A%0A-%20**Single%20binary**%20-%20Each%20app%20compiles%20to%20one%20small%20binary%20(~7MB)%20with%20all%20assets%20embedded%20at%20compile%20time%0A-%20**Minimal%20resource%20usage**%20-%20Apps%20average%20around%20~10MB%20of%20RAM%0A-%20**Self-hosted**%20-%20You%20own%20your%20data%20and%20run%20it%20on%20your%20own%20infrastructure%0A-%20**Simple%20deployment**%20-%20One%20binary%2C%20one%20optional%20%60.env%60%20file%2C%20no%20external%20dependencies%0A-%20**Consistent%20stack**%20-%20All%20apps%20share%20the%20same%20Rust%20stack%20so%20patterns%20are%20transferable%0A%0A%23%23%20Apps%0A%0A%7C%20App%20%7C%20Description%20%7C%0A%7C---%7C---%7C%0A%7C%20%5BSipp%5D(%2Fapps%2Fsipp)%20%7C%20Code%20sharing%20with%20web%20UI%20and%20TUI%20%7C%0A%7C%20%5BFeeds%5D(%2Fapps%2Ffeeds)%20%7C%20RSS%20reader%20with%20FreshRSS%20and%20OPML%20support%20%7C%0A%7C%20%5BParcels%5D(%2Fapps%2Fparcels)%20%7C%20Package%20tracking%20(USPS)%20%7C%0A%7C%20%5BJotts%5D(%2Fapps%2Fjotts)%20%7C%20Markdown%20notes%20%7C%0A%7C%20%5BOG%5D(%2Fapps%2Fog)%20%7C%20Open%20Graph%20tag%20inspector%20%7C%0A%7C%20%5BShrink%5D(%2Fapps%2Fshrink)%20%7C%20Image%20compression%20and%20resizing%20%7C%0A%0A%23%23%20Shared%20Crates%0A%0A%7C%20Crate%20%7C%20Description%20%7C%0A%7C---%7C---%7C%0A%7C%20%60andromeda-auth%60%20%7C%20Session-based%20password%20authentication%20%7C%0A%0AThe%20%60andromeda-auth%60%20crate%20provides%20a%20shared%20authentication%20layer%20used%20across%20apps%20that%20require%20login%2C%20including%20session%20cookies%20and%20constant-time%20password%20verification.%0A%0A%23%23%20License%0A%0A%5BMIT%5D(https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fandromeda%2Fblob%2Fmain%2FLICENSE)%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./skills-VcFKmRnq.js"),[]),path:"/diy/skills",type:"mdx",filePath:"diy/skills.mdx",content:"%23%20Skills%0A%0AAndromeda%20apps%20are%20scaffolded%20using%20%5BClaude%20Code%5D(https%3A%2F%2Fclaude.ai%2Fcode)%20with%20a%20custom%20skill%20called%20%60rust-crud%60.%20This%20page%20explains%20how%20to%20use%20it%20to%20build%20your%20own%20apps%20in%20the%20same%20style.%0A%0A%23%23%20What%20is%20rust-crud%3F%0A%0A%60rust-crud%60%20is%20a%20Claude%20Code%20skill%20that%20scaffolds%20a%20complete%20Rust%20CRUD%20web%20application%20matching%20the%20Andromeda%20stack%3A%0A%0A-%20Axum%20web%20server%20with%20routing%0A-%20SQLite%20database%20with%20rusqlite%0A-%20Askama%20HTML%20templates%0A-%20API%20key%20authentication%0A-%20Embedded%20static%20assets%20via%20rust-embed%0A-%20Dockerfile%20and%20docker-compose.yml%20for%20deployment%0A%0A%23%23%20Using%20the%20Skill%0A%0AIn%20Claude%20Code%2C%20invoke%20the%20skill%20when%20you%20want%20to%20create%20a%20new%20app%3A%0A%0A%60%60%60%0A%2Frust-crud%0A%60%60%60%0A%0ADescribe%20what%20you%20want%20to%20build%20and%20the%20skill%20will%20generate%20a%20complete%2C%20working%20app%20that%20follows%20the%20same%20patterns%20as%20every%20other%20Andromeda%20app.%0A%0A%23%23%20Building%20Your%20Own%20App%0A%0AIf%20you%20want%20to%20add%20a%20new%20app%20to%20the%20workspace%20manually%2C%20follow%20these%20steps%3A%0A%0A%23%23%23%201.%20Create%20the%20app%20directory%0A%0A%60%60%60bash%0Amkdir%20-p%20apps%2Fmy-app%2Fsrc%0Amkdir%20-p%20apps%2Fmy-app%2Ftemplates%0Amkdir%20-p%20apps%2Fmy-app%2Fstatic%0A%60%60%60%0A%0A%23%23%23%202.%20Add%20to%20workspace%0A%0AAdd%20your%20app%20to%20the%20root%20%60Cargo.toml%60%20workspace%20members%3A%0A%0A%60%60%60toml%0A%5Bworkspace%5D%0Amembers%20%3D%20%5B%0A%20%20%20%20%22apps%2Fmy-app%22%2C%0A%20%20%20%20%23%20...existing%20apps%0A%5D%0A%60%60%60%0A%0A%23%23%23%203.%20Set%20up%20Cargo.toml%0A%0A%60%60%60toml%0A%5Bpackage%5D%0Aname%20%3D%20%22my-app%22%0Aversion%20%3D%20%220.1.0%22%0Aedition%20%3D%20%222021%22%0A%0A%5Bdependencies%5D%0Aaxum%20%3D%20%220.8%22%0Atokio%20%3D%20%7B%20version%20%3D%20%221%22%2C%20features%20%3D%20%5B%22full%22%5D%20%7D%0Arusqlite%20%3D%20%7B%20version%20%3D%20%220.32%22%2C%20features%20%3D%20%5B%22bundled%22%5D%20%7D%0Aaskama%20%3D%20%220.12%22%0Aaskama_axum%20%3D%20%220.4%22%0Arust-embed%20%3D%20%228%22%0Atower-http%20%3D%20%7B%20version%20%3D%20%220.6%22%2C%20features%20%3D%20%5B%22cors%22%5D%20%7D%0Aserde%20%3D%20%7B%20version%20%3D%20%221%22%2C%20features%20%3D%20%5B%22derive%22%5D%20%7D%0Adotenvy%20%3D%20%220.15%22%0A%60%60%60%0A%0A%23%23%23%204.%20Follow%20the%20pattern%0A%0AUse%20the%20%5BStack%5D(%2Fdiy%2Fstack)%20page%20as%20a%20reference%20for%20how%20to%20structure%20your%20%60main.rs%60%2C%20%60server.rs%60%2C%20and%20%60db.rs%60%20files.%20Look%20at%20any%20existing%20app%20in%20%60apps%2F%60%20for%20a%20working%20example.%0A%0A%23%23%23%205.%20Build%20and%20run%0A%0A%60%60%60bash%0Acargo%20run%20-p%20my-app%0A%60%60%60%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./skills-VcFKmRnq.js"),[]),path:"/diy/skills.html",type:"mdx",filePath:"diy/skills.mdx",content:"%23%20Skills%0A%0AAndromeda%20apps%20are%20scaffolded%20using%20%5BClaude%20Code%5D(https%3A%2F%2Fclaude.ai%2Fcode)%20with%20a%20custom%20skill%20called%20%60rust-crud%60.%20This%20page%20explains%20how%20to%20use%20it%20to%20build%20your%20own%20apps%20in%20the%20same%20style.%0A%0A%23%23%20What%20is%20rust-crud%3F%0A%0A%60rust-crud%60%20is%20a%20Claude%20Code%20skill%20that%20scaffolds%20a%20complete%20Rust%20CRUD%20web%20application%20matching%20the%20Andromeda%20stack%3A%0A%0A-%20Axum%20web%20server%20with%20routing%0A-%20SQLite%20database%20with%20rusqlite%0A-%20Askama%20HTML%20templates%0A-%20API%20key%20authentication%0A-%20Embedded%20static%20assets%20via%20rust-embed%0A-%20Dockerfile%20and%20docker-compose.yml%20for%20deployment%0A%0A%23%23%20Using%20the%20Skill%0A%0AIn%20Claude%20Code%2C%20invoke%20the%20skill%20when%20you%20want%20to%20create%20a%20new%20app%3A%0A%0A%60%60%60%0A%2Frust-crud%0A%60%60%60%0A%0ADescribe%20what%20you%20want%20to%20build%20and%20the%20skill%20will%20generate%20a%20complete%2C%20working%20app%20that%20follows%20the%20same%20patterns%20as%20every%20other%20Andromeda%20app.%0A%0A%23%23%20Building%20Your%20Own%20App%0A%0AIf%20you%20want%20to%20add%20a%20new%20app%20to%20the%20workspace%20manually%2C%20follow%20these%20steps%3A%0A%0A%23%23%23%201.%20Create%20the%20app%20directory%0A%0A%60%60%60bash%0Amkdir%20-p%20apps%2Fmy-app%2Fsrc%0Amkdir%20-p%20apps%2Fmy-app%2Ftemplates%0Amkdir%20-p%20apps%2Fmy-app%2Fstatic%0A%60%60%60%0A%0A%23%23%23%202.%20Add%20to%20workspace%0A%0AAdd%20your%20app%20to%20the%20root%20%60Cargo.toml%60%20workspace%20members%3A%0A%0A%60%60%60toml%0A%5Bworkspace%5D%0Amembers%20%3D%20%5B%0A%20%20%20%20%22apps%2Fmy-app%22%2C%0A%20%20%20%20%23%20...existing%20apps%0A%5D%0A%60%60%60%0A%0A%23%23%23%203.%20Set%20up%20Cargo.toml%0A%0A%60%60%60toml%0A%5Bpackage%5D%0Aname%20%3D%20%22my-app%22%0Aversion%20%3D%20%220.1.0%22%0Aedition%20%3D%20%222021%22%0A%0A%5Bdependencies%5D%0Aaxum%20%3D%20%220.8%22%0Atokio%20%3D%20%7B%20version%20%3D%20%221%22%2C%20features%20%3D%20%5B%22full%22%5D%20%7D%0Arusqlite%20%3D%20%7B%20version%20%3D%20%220.32%22%2C%20features%20%3D%20%5B%22bundled%22%5D%20%7D%0Aaskama%20%3D%20%220.12%22%0Aaskama_axum%20%3D%20%220.4%22%0Arust-embed%20%3D%20%228%22%0Atower-http%20%3D%20%7B%20version%20%3D%20%220.6%22%2C%20features%20%3D%20%5B%22cors%22%5D%20%7D%0Aserde%20%3D%20%7B%20version%20%3D%20%221%22%2C%20features%20%3D%20%5B%22derive%22%5D%20%7D%0Adotenvy%20%3D%20%220.15%22%0A%60%60%60%0A%0A%23%23%23%204.%20Follow%20the%20pattern%0A%0AUse%20the%20%5BStack%5D(%2Fdiy%2Fstack)%20page%20as%20a%20reference%20for%20how%20to%20structure%20your%20%60main.rs%60%2C%20%60server.rs%60%2C%20and%20%60db.rs%60%20files.%20Look%20at%20any%20existing%20app%20in%20%60apps%2F%60%20for%20a%20working%20example.%0A%0A%23%23%23%205.%20Build%20and%20run%0A%0A%60%60%60bash%0Acargo%20run%20-p%20my-app%0A%60%60%60%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./stack-j78PQFhi.js"),[]),path:"/diy/stack",type:"mdx",filePath:"diy/stack.mdx",content:"%23%20Stack%0A%0AEvery%20app%20in%20Andromeda%20is%20built%20on%20the%20same%20Rust%20stack.%20This%20page%20covers%20the%20core%20dependencies%20and%20how%20they%20fit%20together.%0A%0A%23%23%20Core%20Dependencies%0A%0A%23%23%23%20Axum%0A%0A%5BAxum%5D(https%3A%2F%2Fgithub.com%2Ftokio-rs%2Faxum)%20is%20the%20web%20framework%20powering%20every%20app.%20It%20provides%20routing%2C%20request%20extraction%2C%20middleware%2C%20and%20response%20handling.%20All%20apps%20follow%20a%20similar%20pattern%3A%0A%0A%60%60%60rust%0Alet%20app%20%3D%20Router%3A%3Anew()%0A%20%20%20%20.route(%22%2F%22%2C%20get(index))%0A%20%20%20%20.route(%22%2Fapi%2Fitems%22%2C%20post(create_item))%0A%20%20%20%20.with_state(app_state)%3B%0A%60%60%60%0A%0A%23%23%23%20SQLite%20(rusqlite)%0A%0A%5Brusqlite%5D(https%3A%2F%2Fgithub.com%2Frusqlite%2Frusqlite)%20provides%20the%20storage%20layer.%20Each%20app%20creates%20its%20own%20SQLite%20database%20file%2C%20keeping%20data%20local%20and%20portable.%20No%20external%20database%20server%20needed.%0A%0A%23%23%23%20Askama%0A%0A%5BAskama%5D(https%3A%2F%2Fgithub.com%2Fdjc%2Faskama)%20handles%20HTML%20templating%20with%20compile-time%20checked%20templates.%20Templates%20live%20in%20a%20%60templates%2F%60%20directory%20and%20are%20type-safe%20Rust%20structs%3A%0A%0A%60%60%60rust%0A%23%5Bderive(Template)%5D%0A%23%5Btemplate(path%20%3D%20%22index.html%22)%5D%0Astruct%20IndexTemplate%20%7B%0A%20%20%20%20items%3A%20Vec%3CItem%3E%2C%0A%7D%0A%60%60%60%0A%0A%23%23%23%20rust-embed%0A%0A%5Brust-embed%5D(https%3A%2F%2Fgithub.com%2Fpyrossh%2Frust-embed)%20embeds%20static%20assets%20(CSS%2C%20fonts%2C%20images)%20directly%20into%20the%20binary%20at%20compile%20time.%20This%20is%20what%20makes%20each%20app%20a%20single%2C%20self-contained%20binary%20with%20no%20external%20file%20dependencies.%0A%0A%23%23%23%20Tokio%0A%0A%5BTokio%5D(https%3A%2F%2Ftokio.rs)%20provides%20the%20async%20runtime%20that%20Axum%20runs%20on.%0A%0A%23%23%20Shared%20Crate%3A%20andromeda-auth%0A%0AThe%20%60andromeda-auth%60%20crate%20provides%20session-based%20password%20authentication%20used%20across%20apps%20that%20require%20login.%20It%20handles%3A%0A%0A-%20Constant-time%20password%20verification%0A-%20Session%20cookie%20management%0A-%20Secure%20cookie%20configuration%20via%20%60COOKIE_SECURE%60%20env%20var%0A%0A%23%23%20App%20Pattern%0A%0AEvery%20app%20follows%20a%20consistent%20structure%3A%0A%0A%60%60%60%0Aapp%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20src%2F%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20main.rs%20%20%20%20%20%20%20%20%23%20Entry%20point%2C%20env%20vars%2C%20starts%20server%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20server.rs%20%20%20%20%20%20%23%20Axum%20routes%20and%20handlers%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20db.rs%20%20%20%20%20%20%20%20%20%20%23%20SQLite%20database%20layer%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20auth.rs%20%20%20%20%20%20%20%20%23%20Authentication%20(if%20needed)%0A%E2%94%9C%E2%94%80%E2%94%80%20templates%2F%20%20%20%20%20%20%20%20%20%23%20Askama%20HTML%20templates%0A%E2%94%9C%E2%94%80%E2%94%80%20static%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Fonts%2C%20favicons%2C%20styles%0A%E2%94%9C%E2%94%80%E2%94%80%20Dockerfile%0A%E2%94%94%E2%94%80%E2%94%80%20docker-compose.yml%0A%60%60%60%0A%0AThis%20consistency%20means%20once%20you%20understand%20one%20app%2C%20you%20can%20navigate%20any%20of%20them.%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./stack-j78PQFhi.js"),[]),path:"/diy/stack.html",type:"mdx",filePath:"diy/stack.mdx",content:"%23%20Stack%0A%0AEvery%20app%20in%20Andromeda%20is%20built%20on%20the%20same%20Rust%20stack.%20This%20page%20covers%20the%20core%20dependencies%20and%20how%20they%20fit%20together.%0A%0A%23%23%20Core%20Dependencies%0A%0A%23%23%23%20Axum%0A%0A%5BAxum%5D(https%3A%2F%2Fgithub.com%2Ftokio-rs%2Faxum)%20is%20the%20web%20framework%20powering%20every%20app.%20It%20provides%20routing%2C%20request%20extraction%2C%20middleware%2C%20and%20response%20handling.%20All%20apps%20follow%20a%20similar%20pattern%3A%0A%0A%60%60%60rust%0Alet%20app%20%3D%20Router%3A%3Anew()%0A%20%20%20%20.route(%22%2F%22%2C%20get(index))%0A%20%20%20%20.route(%22%2Fapi%2Fitems%22%2C%20post(create_item))%0A%20%20%20%20.with_state(app_state)%3B%0A%60%60%60%0A%0A%23%23%23%20SQLite%20(rusqlite)%0A%0A%5Brusqlite%5D(https%3A%2F%2Fgithub.com%2Frusqlite%2Frusqlite)%20provides%20the%20storage%20layer.%20Each%20app%20creates%20its%20own%20SQLite%20database%20file%2C%20keeping%20data%20local%20and%20portable.%20No%20external%20database%20server%20needed.%0A%0A%23%23%23%20Askama%0A%0A%5BAskama%5D(https%3A%2F%2Fgithub.com%2Fdjc%2Faskama)%20handles%20HTML%20templating%20with%20compile-time%20checked%20templates.%20Templates%20live%20in%20a%20%60templates%2F%60%20directory%20and%20are%20type-safe%20Rust%20structs%3A%0A%0A%60%60%60rust%0A%23%5Bderive(Template)%5D%0A%23%5Btemplate(path%20%3D%20%22index.html%22)%5D%0Astruct%20IndexTemplate%20%7B%0A%20%20%20%20items%3A%20Vec%3CItem%3E%2C%0A%7D%0A%60%60%60%0A%0A%23%23%23%20rust-embed%0A%0A%5Brust-embed%5D(https%3A%2F%2Fgithub.com%2Fpyrossh%2Frust-embed)%20embeds%20static%20assets%20(CSS%2C%20fonts%2C%20images)%20directly%20into%20the%20binary%20at%20compile%20time.%20This%20is%20what%20makes%20each%20app%20a%20single%2C%20self-contained%20binary%20with%20no%20external%20file%20dependencies.%0A%0A%23%23%23%20Tokio%0A%0A%5BTokio%5D(https%3A%2F%2Ftokio.rs)%20provides%20the%20async%20runtime%20that%20Axum%20runs%20on.%0A%0A%23%23%20Shared%20Crate%3A%20andromeda-auth%0A%0AThe%20%60andromeda-auth%60%20crate%20provides%20session-based%20password%20authentication%20used%20across%20apps%20that%20require%20login.%20It%20handles%3A%0A%0A-%20Constant-time%20password%20verification%0A-%20Session%20cookie%20management%0A-%20Secure%20cookie%20configuration%20via%20%60COOKIE_SECURE%60%20env%20var%0A%0A%23%23%20App%20Pattern%0A%0AEvery%20app%20follows%20a%20consistent%20structure%3A%0A%0A%60%60%60%0Aapp%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20src%2F%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20main.rs%20%20%20%20%20%20%20%20%23%20Entry%20point%2C%20env%20vars%2C%20starts%20server%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20server.rs%20%20%20%20%20%20%23%20Axum%20routes%20and%20handlers%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20db.rs%20%20%20%20%20%20%20%20%20%20%23%20SQLite%20database%20layer%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20auth.rs%20%20%20%20%20%20%20%20%23%20Authentication%20(if%20needed)%0A%E2%94%9C%E2%94%80%E2%94%80%20templates%2F%20%20%20%20%20%20%20%20%20%23%20Askama%20HTML%20templates%0A%E2%94%9C%E2%94%80%E2%94%80%20static%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Fonts%2C%20favicons%2C%20styles%0A%E2%94%9C%E2%94%80%E2%94%80%20Dockerfile%0A%E2%94%94%E2%94%80%E2%94%80%20docker-compose.yml%0A%60%60%60%0A%0AThis%20consistency%20means%20once%20you%20understand%20one%20app%2C%20you%20can%20navigate%20any%20of%20them.%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./feeds-D1cR5X6g.js"),[]),path:"/apps/feeds",type:"mdx",filePath:"apps/feeds.mdx",content:"%23%20Feeds%0A%0AMinimal%20RSS%20Feeds%0A%0A%23%23%20Overview%0A%0AFeeds%20is%20a%20minimal%20RSS%20reader%20that%20mimics%20the%20original%20experience%20of%20RSS.%20It's%20just%20a%20list%20of%20posts.%20No%20categories%2C%20no%20marking%20a%20post%20read%20or%20unread%2C%20and%20there%20is%20no%20in-app%20reading.%20With%20this%20approach%20you%20have%20to%20read%20the%20post%20on%20the%20author's%20personal%20website%20and%20experience%20it%20in%20its%20original%20context.%0A%0A-%20Single%20Rust%20binary%20with%20embedded%20assets%0A-%20Multiple%20feed%20sources%3A%20URL%20params%2C%20OPML%20file%2C%20or%20FreshRSS%20API%0A-%20Password-protected%20admin%20panel%20for%20managing%20subscriptions%0A-%20Feeds%20API%20with%20JSON%20and%20OPML%20export%0A-%20Dark%20themed%20UI%20with%20Commit%20Mono%20font%0A%0A%23%23%20Quickstart%0A%0A%60%60%60bash%0Agit%20clone%20https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fandromeda.git%0Acd%20andromeda%0Acargo%20run%20-p%20feeds%0A%23%20Server%20running%20on%20http%3A%2F%2Flocalhost%3A3000%0A%60%60%60%0A%0A%23%23%23%20Environment%20Variables%0A%0A%7C%20Variable%20%7C%20Description%20%7C%20Default%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20%60FRESHRSS_URL%60%20%7C%20URL%20of%20your%20FreshRSS%20instance%20%7C%20--%20%7C%0A%7C%20%60FRESHRSS_USERNAME%60%20%7C%20FreshRSS%20username%20%7C%20--%20%7C%0A%7C%20%60FRESHRSS_PASSWORD%60%20%7C%20FreshRSS%20password%20%7C%20--%20%7C%0A%7C%20%60ADMIN_PASSWORD%60%20%7C%20Password%20for%20the%20admin%20panel%20%7C%20--%20%7C%0A%7C%20%60COOKIE_SECURE%60%20%7C%20Enable%20HTTPS-only%20cookies%20%7C%20%60false%60%20%7C%0A%0A%23%23%20Usage%0A%0AThere%20are%20several%20built-in%20ways%20to%20source%20RSS%20feeds.%0A%0A%23%23%23%20URL%20Query%20Param%0A%0AOnce%20you%20have%20the%20app%20running%20you%20can%20add%20the%20following%20to%20the%20URL%20to%20source%20an%20RSS%20feed%3A%0A%0A%60%60%60%0A%3Furl%3Dhttps%3A%2F%2Fbearblog.dev%2Fdiscover%2Ffeed%2F%0A%60%60%60%0A%0AYou%20can%20also%20add%20multiple%20URLs%20by%20using%20commas%20to%20separate%20them%3A%0A%0A%60%60%60%0A%3Furls%3Dhttps%3A%2F%2Fbearblog.dev%2Fdiscover%2Ffeed%2F%2Chttps%3A%2F%2Fbearblog.stevedylan.dev%2Ffeed%2F%0A%60%60%60%0A%0A%23%23%23%20OPML%20File%0A%0AIf%20you%20save%20a%20%60feeds.opml%60%20file%20in%20the%20root%20of%20the%20project%20the%20app%20will%20automatically%20source%20it%20and%20fetch%20the%20posts%20for%20the%20feeds%20inside.%0A%0A%23%23%23%20FreshRSS%20API%0A%0AIf%20neither%20of%20the%20above%20are%20provided%20the%20app%20will%20default%20to%20using%20a%20FreshRSS%20API%20instance.%20Set%20the%20following%20environment%20variables%3A%0A%0A%60%60%60%0AFRESHRSS_URL%3D%0AFRESHRSS_USERNAME%3D%0AFRESHRSS_PASSWORD%3D%0A%60%60%60%0A%0A%23%23%23%20Admin%20Panel%0A%0AFeeds%20includes%20a%20password-protected%20admin%20panel%20at%20%60%2Fadmin%60%20for%20managing%20your%20FreshRSS%20subscriptions.%20Set%20the%20%60ADMIN_PASSWORD%60%20environment%20variable%20to%20enable%20it.%20From%20the%20admin%20panel%20you%20can%20view%20your%20current%20subscriptions%20and%20add%20new%20feeds%20directly%20to%20your%20FreshRSS%20instance.%0A%0A%23%23%23%20Feeds%20API%0A%0AThe%20%60%2Ffeeds%60%20endpoint%20exports%20your%20FreshRSS%20subscriptions%20in%20JSON%20or%20OPML%20format%3A%0A%0A%60%60%60%0A%2Ffeeds%3Fformat%3Djson%0A%2Ffeeds%3Fformat%3Dopml%0A%60%60%60%0A%0A%23%23%20Structure%0A%0A%60%60%60%0Afeeds%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20src%2F%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20main.rs%20%20%20%20%20%20%20%20%23%20Axum%20server%20with%20routing%2C%20templates%2C%20and%20static%20asset%20serving%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20feeds.rs%20%20%20%20%20%20%20%23%20Feed%20fetching%2C%20OPML%20parsing%2C%20and%20FreshRSS%20API%20integration%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20auth.rs%20%20%20%20%20%20%20%20%23%20Session-based%20authentication%20with%20constant-time%20password%20verification%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20models.rs%20%20%20%20%20%20%23%20Data%20structures%20for%20feeds%20and%20FreshRSS%20responses%0A%E2%94%9C%E2%94%80%E2%94%80%20templates%2F%20%20%20%20%20%20%20%20%20%23%20Askama%20HTML%20templates%0A%E2%94%9C%E2%94%80%E2%94%80%20assets%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Static%20assets%20embedded%20at%20compile%20time%20via%20rust-embed%0A%E2%94%9C%E2%94%80%E2%94%80%20Dockerfile%0A%E2%94%94%E2%94%80%E2%94%80%20docker-compose.yml%0A%60%60%60%0A%0A%23%23%20Deployment%0A%0A%23%23%23%20Railway%0A%0A%5B!%5BDeploy%20on%20Railway%5D(https%3A%2F%2Frailway.com%2Fbutton.svg)%5D(https%3A%2F%2Frailway.com%2Fdeploy%2FEzvmhx%3FreferralCode%3DJGcIp6)%0A%0A%23%23%23%20Docker%0A%0A%60%60%60bash%0Acd%20apps%2Ffeeds%0Acp%20.env.sample%20.env%0A%23%20Edit%20.env%20with%20your%20credentials%0Adocker%20compose%20up%20-d%0A%60%60%60%0A%0A%23%23%23%20Binary%0A%0A%60%60%60bash%0Acargo%20build%20--release%20-p%20feeds%0A%60%60%60%0A%0AThe%20resulting%20binary%20is%20self-contained%20with%20all%20assets%20embedded.%20Copy%20it%20to%20your%20server%20with%20a%20configured%20%60.env%60%20file%20and%20run%20it%20directly.%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./feeds-D1cR5X6g.js"),[]),path:"/apps/feeds.html",type:"mdx",filePath:"apps/feeds.mdx",content:"%23%20Feeds%0A%0AMinimal%20RSS%20Feeds%0A%0A%23%23%20Overview%0A%0AFeeds%20is%20a%20minimal%20RSS%20reader%20that%20mimics%20the%20original%20experience%20of%20RSS.%20It's%20just%20a%20list%20of%20posts.%20No%20categories%2C%20no%20marking%20a%20post%20read%20or%20unread%2C%20and%20there%20is%20no%20in-app%20reading.%20With%20this%20approach%20you%20have%20to%20read%20the%20post%20on%20the%20author's%20personal%20website%20and%20experience%20it%20in%20its%20original%20context.%0A%0A-%20Single%20Rust%20binary%20with%20embedded%20assets%0A-%20Multiple%20feed%20sources%3A%20URL%20params%2C%20OPML%20file%2C%20or%20FreshRSS%20API%0A-%20Password-protected%20admin%20panel%20for%20managing%20subscriptions%0A-%20Feeds%20API%20with%20JSON%20and%20OPML%20export%0A-%20Dark%20themed%20UI%20with%20Commit%20Mono%20font%0A%0A%23%23%20Quickstart%0A%0A%60%60%60bash%0Agit%20clone%20https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fandromeda.git%0Acd%20andromeda%0Acargo%20run%20-p%20feeds%0A%23%20Server%20running%20on%20http%3A%2F%2Flocalhost%3A3000%0A%60%60%60%0A%0A%23%23%23%20Environment%20Variables%0A%0A%7C%20Variable%20%7C%20Description%20%7C%20Default%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20%60FRESHRSS_URL%60%20%7C%20URL%20of%20your%20FreshRSS%20instance%20%7C%20--%20%7C%0A%7C%20%60FRESHRSS_USERNAME%60%20%7C%20FreshRSS%20username%20%7C%20--%20%7C%0A%7C%20%60FRESHRSS_PASSWORD%60%20%7C%20FreshRSS%20password%20%7C%20--%20%7C%0A%7C%20%60ADMIN_PASSWORD%60%20%7C%20Password%20for%20the%20admin%20panel%20%7C%20--%20%7C%0A%7C%20%60COOKIE_SECURE%60%20%7C%20Enable%20HTTPS-only%20cookies%20%7C%20%60false%60%20%7C%0A%0A%23%23%20Usage%0A%0AThere%20are%20several%20built-in%20ways%20to%20source%20RSS%20feeds.%0A%0A%23%23%23%20URL%20Query%20Param%0A%0AOnce%20you%20have%20the%20app%20running%20you%20can%20add%20the%20following%20to%20the%20URL%20to%20source%20an%20RSS%20feed%3A%0A%0A%60%60%60%0A%3Furl%3Dhttps%3A%2F%2Fbearblog.dev%2Fdiscover%2Ffeed%2F%0A%60%60%60%0A%0AYou%20can%20also%20add%20multiple%20URLs%20by%20using%20commas%20to%20separate%20them%3A%0A%0A%60%60%60%0A%3Furls%3Dhttps%3A%2F%2Fbearblog.dev%2Fdiscover%2Ffeed%2F%2Chttps%3A%2F%2Fbearblog.stevedylan.dev%2Ffeed%2F%0A%60%60%60%0A%0A%23%23%23%20OPML%20File%0A%0AIf%20you%20save%20a%20%60feeds.opml%60%20file%20in%20the%20root%20of%20the%20project%20the%20app%20will%20automatically%20source%20it%20and%20fetch%20the%20posts%20for%20the%20feeds%20inside.%0A%0A%23%23%23%20FreshRSS%20API%0A%0AIf%20neither%20of%20the%20above%20are%20provided%20the%20app%20will%20default%20to%20using%20a%20FreshRSS%20API%20instance.%20Set%20the%20following%20environment%20variables%3A%0A%0A%60%60%60%0AFRESHRSS_URL%3D%0AFRESHRSS_USERNAME%3D%0AFRESHRSS_PASSWORD%3D%0A%60%60%60%0A%0A%23%23%23%20Admin%20Panel%0A%0AFeeds%20includes%20a%20password-protected%20admin%20panel%20at%20%60%2Fadmin%60%20for%20managing%20your%20FreshRSS%20subscriptions.%20Set%20the%20%60ADMIN_PASSWORD%60%20environment%20variable%20to%20enable%20it.%20From%20the%20admin%20panel%20you%20can%20view%20your%20current%20subscriptions%20and%20add%20new%20feeds%20directly%20to%20your%20FreshRSS%20instance.%0A%0A%23%23%23%20Feeds%20API%0A%0AThe%20%60%2Ffeeds%60%20endpoint%20exports%20your%20FreshRSS%20subscriptions%20in%20JSON%20or%20OPML%20format%3A%0A%0A%60%60%60%0A%2Ffeeds%3Fformat%3Djson%0A%2Ffeeds%3Fformat%3Dopml%0A%60%60%60%0A%0A%23%23%20Structure%0A%0A%60%60%60%0Afeeds%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20src%2F%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20main.rs%20%20%20%20%20%20%20%20%23%20Axum%20server%20with%20routing%2C%20templates%2C%20and%20static%20asset%20serving%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20feeds.rs%20%20%20%20%20%20%20%23%20Feed%20fetching%2C%20OPML%20parsing%2C%20and%20FreshRSS%20API%20integration%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20auth.rs%20%20%20%20%20%20%20%20%23%20Session-based%20authentication%20with%20constant-time%20password%20verification%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20models.rs%20%20%20%20%20%20%23%20Data%20structures%20for%20feeds%20and%20FreshRSS%20responses%0A%E2%94%9C%E2%94%80%E2%94%80%20templates%2F%20%20%20%20%20%20%20%20%20%23%20Askama%20HTML%20templates%0A%E2%94%9C%E2%94%80%E2%94%80%20assets%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Static%20assets%20embedded%20at%20compile%20time%20via%20rust-embed%0A%E2%94%9C%E2%94%80%E2%94%80%20Dockerfile%0A%E2%94%94%E2%94%80%E2%94%80%20docker-compose.yml%0A%60%60%60%0A%0A%23%23%20Deployment%0A%0A%23%23%23%20Railway%0A%0A%5B!%5BDeploy%20on%20Railway%5D(https%3A%2F%2Frailway.com%2Fbutton.svg)%5D(https%3A%2F%2Frailway.com%2Fdeploy%2FEzvmhx%3FreferralCode%3DJGcIp6)%0A%0A%23%23%23%20Docker%0A%0A%60%60%60bash%0Acd%20apps%2Ffeeds%0Acp%20.env.sample%20.env%0A%23%20Edit%20.env%20with%20your%20credentials%0Adocker%20compose%20up%20-d%0A%60%60%60%0A%0A%23%23%23%20Binary%0A%0A%60%60%60bash%0Acargo%20build%20--release%20-p%20feeds%0A%60%60%60%0A%0AThe%20resulting%20binary%20is%20self-contained%20with%20all%20assets%20embedded.%20Copy%20it%20to%20your%20server%20with%20a%20configured%20%60.env%60%20file%20and%20run%20it%20directly.%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./jotts-St5ii0O4.js"),[]),path:"/apps/jotts",type:"mdx",filePath:"apps/jotts.mdx",content:"%23%20Jotts%0A%0AA%20minimal%20notes%20app%0A%0A%23%23%20Overview%0A%0AA%20simple%2C%20self-hosted%20markdown%20note%20app%20built%20with%20Rust.%0A%0A-%20Single%20~7MB%20Rust%20binary%20with%20embedded%20assets%0A-%20Password%20authentication%20with%20session%20cookies%0A-%20Create%2C%20edit%2C%20and%20delete%20markdown%20notes%0A-%20Markdown%20rendering%20with%20strikethrough%2C%20tables%2C%20and%20task%20lists%0A-%20Dark%20themed%20UI%20with%20Commit%20Mono%20font%0A-%20SQLite%20for%20persistent%20storage%0A%0A%23%23%20Quickstart%0A%0A%60%60%60bash%0Agit%20clone%20https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fandromeda.git%0Acd%20andromeda%0Acp%20apps%2Fjotts%2F.env.example%20.env%0A%23%20Edit%20.env%20with%20your%20password%0Acargo%20run%20-p%20jotts%0A%60%60%60%0A%0A%23%23%23%20Environment%20Variables%0A%0A%7C%20Variable%20%7C%20Description%20%7C%20Default%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20%60JOTTS_PASSWORD%60%20%7C%20Password%20for%20login%20authentication%20%7C%20%60changeme%60%20%7C%0A%7C%20%60JOTTS_DB_PATH%60%20%7C%20SQLite%20database%20file%20path%20%7C%20%60jotts.sqlite%60%20%7C%0A%7C%20%60HOST%60%20%7C%20Server%20bind%20address%20%7C%20%60127.0.0.1%60%20%7C%0A%7C%20%60PORT%60%20%7C%20Server%20port%20%7C%20%603000%60%20%7C%0A%7C%20%60COOKIE_SECURE%60%20%7C%20Enable%20HTTPS-only%20cookies%20%7C%20%60false%60%20%7C%0A%0A%23%23%20Structure%0A%0A%60%60%60%0Ajotts%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20src%2F%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20main.rs%20%20%20%20%20%20%20%20%23%20App%20entrypoint%2C%20env%20vars%2C%20starts%20server%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20server.rs%20%20%20%20%20%20%23%20Axum%20router%2C%20HTTP%20handlers%2C%20and%20templates%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20auth.rs%20%20%20%20%20%20%20%20%23%20Password%20verification%20and%20session%20management%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20db.rs%20%20%20%20%20%20%20%20%20%20%23%20SQLite%20database%20layer%20(notes%2C%20sessions)%0A%E2%94%9C%E2%94%80%E2%94%80%20templates%2F%20%20%20%20%20%20%20%20%20%23%20Askama%20HTML%20templates%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20base.html%20%20%20%20%20%20%23%20Base%20layout%20with%20header%20and%20nav%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20login.html%20%20%20%20%20%23%20Login%20page%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20index.html%20%20%20%20%20%23%20Note%20list%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20view.html%20%20%20%20%20%20%23%20Single%20note%20display%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20new.html%20%20%20%20%20%20%20%23%20Create%20note%20form%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20edit.html%20%20%20%20%20%20%23%20Edit%20note%20form%0A%E2%94%9C%E2%94%80%E2%94%80%20static%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Favicons%2C%20og%3Aimage%2C%20styles%2C%20and%20webmanifest%0A%E2%94%9C%E2%94%80%E2%94%80%20assets%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Commit%20Mono%20font%20files%0A%E2%94%9C%E2%94%80%E2%94%80%20Dockerfile%0A%E2%94%94%E2%94%80%E2%94%80%20docker-compose.yml%0A%60%60%60%0A%0A%23%23%20Deployment%0A%0A%23%23%23%20Railway%0A%0A%5B!%5BDeploy%20on%20Railway%5D(https%3A%2F%2Frailway.com%2Fbutton.svg)%5D(https%3A%2F%2Frailway.com%2Fdeploy%2FDLhUhH%3FreferralCode%3DJGcIp6)%0A%0A%23%23%23%20Docker%0A%0A%60%60%60bash%0Acd%20apps%2Fjotts%0Acp%20.env.example%20.env%0A%23%20Edit%20.env%20with%20your%20password%0Adocker%20compose%20up%20-d%0A%60%60%60%0A%0AThis%20will%20start%20Jotts%20on%20port%20%603000%60%20with%20a%20persistent%20volume%20for%20the%20SQLite%20database.%0A%0A%23%23%23%20Binary%0A%0A%60%60%60bash%0Acargo%20build%20--release%20-p%20jotts%0A%60%60%60%0A%0AThe%20resulting%20binary%20is%20self-contained%20with%20all%20assets%20embedded.%20Copy%20it%20to%20your%20server%20with%20a%20configured%20%60.env%60%20file%20and%20run%20it%20directly.%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./jotts-St5ii0O4.js"),[]),path:"/apps/jotts.html",type:"mdx",filePath:"apps/jotts.mdx",content:"%23%20Jotts%0A%0AA%20minimal%20notes%20app%0A%0A%23%23%20Overview%0A%0AA%20simple%2C%20self-hosted%20markdown%20note%20app%20built%20with%20Rust.%0A%0A-%20Single%20~7MB%20Rust%20binary%20with%20embedded%20assets%0A-%20Password%20authentication%20with%20session%20cookies%0A-%20Create%2C%20edit%2C%20and%20delete%20markdown%20notes%0A-%20Markdown%20rendering%20with%20strikethrough%2C%20tables%2C%20and%20task%20lists%0A-%20Dark%20themed%20UI%20with%20Commit%20Mono%20font%0A-%20SQLite%20for%20persistent%20storage%0A%0A%23%23%20Quickstart%0A%0A%60%60%60bash%0Agit%20clone%20https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fandromeda.git%0Acd%20andromeda%0Acp%20apps%2Fjotts%2F.env.example%20.env%0A%23%20Edit%20.env%20with%20your%20password%0Acargo%20run%20-p%20jotts%0A%60%60%60%0A%0A%23%23%23%20Environment%20Variables%0A%0A%7C%20Variable%20%7C%20Description%20%7C%20Default%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20%60JOTTS_PASSWORD%60%20%7C%20Password%20for%20login%20authentication%20%7C%20%60changeme%60%20%7C%0A%7C%20%60JOTTS_DB_PATH%60%20%7C%20SQLite%20database%20file%20path%20%7C%20%60jotts.sqlite%60%20%7C%0A%7C%20%60HOST%60%20%7C%20Server%20bind%20address%20%7C%20%60127.0.0.1%60%20%7C%0A%7C%20%60PORT%60%20%7C%20Server%20port%20%7C%20%603000%60%20%7C%0A%7C%20%60COOKIE_SECURE%60%20%7C%20Enable%20HTTPS-only%20cookies%20%7C%20%60false%60%20%7C%0A%0A%23%23%20Structure%0A%0A%60%60%60%0Ajotts%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20src%2F%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20main.rs%20%20%20%20%20%20%20%20%23%20App%20entrypoint%2C%20env%20vars%2C%20starts%20server%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20server.rs%20%20%20%20%20%20%23%20Axum%20router%2C%20HTTP%20handlers%2C%20and%20templates%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20auth.rs%20%20%20%20%20%20%20%20%23%20Password%20verification%20and%20session%20management%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20db.rs%20%20%20%20%20%20%20%20%20%20%23%20SQLite%20database%20layer%20(notes%2C%20sessions)%0A%E2%94%9C%E2%94%80%E2%94%80%20templates%2F%20%20%20%20%20%20%20%20%20%23%20Askama%20HTML%20templates%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20base.html%20%20%20%20%20%20%23%20Base%20layout%20with%20header%20and%20nav%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20login.html%20%20%20%20%20%23%20Login%20page%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20index.html%20%20%20%20%20%23%20Note%20list%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20view.html%20%20%20%20%20%20%23%20Single%20note%20display%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20new.html%20%20%20%20%20%20%20%23%20Create%20note%20form%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20edit.html%20%20%20%20%20%20%23%20Edit%20note%20form%0A%E2%94%9C%E2%94%80%E2%94%80%20static%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Favicons%2C%20og%3Aimage%2C%20styles%2C%20and%20webmanifest%0A%E2%94%9C%E2%94%80%E2%94%80%20assets%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Commit%20Mono%20font%20files%0A%E2%94%9C%E2%94%80%E2%94%80%20Dockerfile%0A%E2%94%94%E2%94%80%E2%94%80%20docker-compose.yml%0A%60%60%60%0A%0A%23%23%20Deployment%0A%0A%23%23%23%20Railway%0A%0A%5B!%5BDeploy%20on%20Railway%5D(https%3A%2F%2Frailway.com%2Fbutton.svg)%5D(https%3A%2F%2Frailway.com%2Fdeploy%2FDLhUhH%3FreferralCode%3DJGcIp6)%0A%0A%23%23%23%20Docker%0A%0A%60%60%60bash%0Acd%20apps%2Fjotts%0Acp%20.env.example%20.env%0A%23%20Edit%20.env%20with%20your%20password%0Adocker%20compose%20up%20-d%0A%60%60%60%0A%0AThis%20will%20start%20Jotts%20on%20port%20%603000%60%20with%20a%20persistent%20volume%20for%20the%20SQLite%20database.%0A%0A%23%23%23%20Binary%0A%0A%60%60%60bash%0Acargo%20build%20--release%20-p%20jotts%0A%60%60%60%0A%0AThe%20resulting%20binary%20is%20self-contained%20with%20all%20assets%20embedded.%20Copy%20it%20to%20your%20server%20with%20a%20configured%20%60.env%60%20file%20and%20run%20it%20directly.%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./og-BdkDok6k.js"),[]),path:"/apps/og",type:"mdx",filePath:"apps/og.mdx",content:"%23%20OG%0A%0AA%20simple%20web%20tool%20for%20inspecting%20Open%20Graph%20tags%20on%20any%20URL.%0A%0A%23%23%20Overview%0A%0AA%20self-hosted%20Open%20Graph%20tag%20inspector%20built%20with%20Rust.%20Enter%20any%20URL%20and%20instantly%20see%20its%20OG%20metadata.%0A%0A-%20Single%20Rust%20binary%20with%20embedded%20assets%0A-%20Inspects%20title%2C%20description%2C%20image%2C%20and%20other%20OG%20tags%0A-%20Dark%20themed%20UI%20with%20Commit%20Mono%20font%0A-%20No%20database%20needed%20--%20fully%20stateless%0A%0A%23%23%20Quickstart%0A%0A%60%60%60bash%0Agit%20clone%20https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fandromeda.git%0Acd%20andromeda%0Acargo%20run%20-p%20og%0A%60%60%60%0A%0A%23%23%23%20Environment%20Variables%0A%0A%7C%20Variable%20%7C%20Description%20%7C%20Default%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20%60PORT%60%20%7C%20Server%20port%20%7C%20%603000%60%20%7C%0A%0A%23%23%20Structure%0A%0A%60%60%60%0Aog%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20src%2F%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20main.rs%20%20%20%20%20%20%20%20%23%20Entry%20point%20and%20server%20startup%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20server.rs%20%20%20%20%20%20%23%20Axum%20routes%20and%20request%20handling%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20og.rs%20%20%20%20%20%20%20%20%20%20%23%20Open%20Graph%20tag%20fetching%20and%20parsing%0A%E2%94%9C%E2%94%80%E2%94%80%20templates%2F%20%20%20%20%20%20%20%20%20%23%20Askama%20HTML%20templates%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20base.html%20%20%20%20%20%20%23%20Base%20layout%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20index.html%20%20%20%20%20%23%20Search%20form%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20results.html%20%20%20%23%20OG%20tag%20results%20display%0A%E2%94%9C%E2%94%80%E2%94%80%20static%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Fonts%2C%20favicons%2C%20and%20styles%0A%E2%94%9C%E2%94%80%E2%94%80%20Dockerfile%0A%E2%94%94%E2%94%80%E2%94%80%20docker-compose.yml%0A%60%60%60%0A%0A%23%23%20Deployment%0A%0A%23%23%23%20Railway%0A%0A%5B!%5BDeploy%20on%20Railway%5D(https%3A%2F%2Frailway.com%2Fbutton.svg)%5D(https%3A%2F%2Frailway.com%2Fdeploy%2FOdXBt_%3FreferralCode%3DJGcIp6)%0A%0A%23%23%23%20Docker%0A%0A%60%60%60bash%0Acd%20apps%2Fog%0Adocker%20compose%20up%20-d%0A%60%60%60%0A%0A%23%23%23%20Binary%0A%0A%60%60%60bash%0Acargo%20build%20--release%20-p%20og%0A%60%60%60%0A%0AThe%20resulting%20binary%20is%20self-contained%20with%20all%20assets%20embedded.%20Copy%20it%20to%20your%20server%20and%20run%20it%20directly.%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./og-BdkDok6k.js"),[]),path:"/apps/og.html",type:"mdx",filePath:"apps/og.mdx",content:"%23%20OG%0A%0AA%20simple%20web%20tool%20for%20inspecting%20Open%20Graph%20tags%20on%20any%20URL.%0A%0A%23%23%20Overview%0A%0AA%20self-hosted%20Open%20Graph%20tag%20inspector%20built%20with%20Rust.%20Enter%20any%20URL%20and%20instantly%20see%20its%20OG%20metadata.%0A%0A-%20Single%20Rust%20binary%20with%20embedded%20assets%0A-%20Inspects%20title%2C%20description%2C%20image%2C%20and%20other%20OG%20tags%0A-%20Dark%20themed%20UI%20with%20Commit%20Mono%20font%0A-%20No%20database%20needed%20--%20fully%20stateless%0A%0A%23%23%20Quickstart%0A%0A%60%60%60bash%0Agit%20clone%20https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fandromeda.git%0Acd%20andromeda%0Acargo%20run%20-p%20og%0A%60%60%60%0A%0A%23%23%23%20Environment%20Variables%0A%0A%7C%20Variable%20%7C%20Description%20%7C%20Default%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20%60PORT%60%20%7C%20Server%20port%20%7C%20%603000%60%20%7C%0A%0A%23%23%20Structure%0A%0A%60%60%60%0Aog%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20src%2F%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20main.rs%20%20%20%20%20%20%20%20%23%20Entry%20point%20and%20server%20startup%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20server.rs%20%20%20%20%20%20%23%20Axum%20routes%20and%20request%20handling%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20og.rs%20%20%20%20%20%20%20%20%20%20%23%20Open%20Graph%20tag%20fetching%20and%20parsing%0A%E2%94%9C%E2%94%80%E2%94%80%20templates%2F%20%20%20%20%20%20%20%20%20%23%20Askama%20HTML%20templates%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20base.html%20%20%20%20%20%20%23%20Base%20layout%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20index.html%20%20%20%20%20%23%20Search%20form%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20results.html%20%20%20%23%20OG%20tag%20results%20display%0A%E2%94%9C%E2%94%80%E2%94%80%20static%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Fonts%2C%20favicons%2C%20and%20styles%0A%E2%94%9C%E2%94%80%E2%94%80%20Dockerfile%0A%E2%94%94%E2%94%80%E2%94%80%20docker-compose.yml%0A%60%60%60%0A%0A%23%23%20Deployment%0A%0A%23%23%23%20Railway%0A%0A%5B!%5BDeploy%20on%20Railway%5D(https%3A%2F%2Frailway.com%2Fbutton.svg)%5D(https%3A%2F%2Frailway.com%2Fdeploy%2FOdXBt_%3FreferralCode%3DJGcIp6)%0A%0A%23%23%23%20Docker%0A%0A%60%60%60bash%0Acd%20apps%2Fog%0Adocker%20compose%20up%20-d%0A%60%60%60%0A%0A%23%23%23%20Binary%0A%0A%60%60%60bash%0Acargo%20build%20--release%20-p%20og%0A%60%60%60%0A%0AThe%20resulting%20binary%20is%20self-contained%20with%20all%20assets%20embedded.%20Copy%20it%20to%20your%20server%20and%20run%20it%20directly.%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./parcels-C9RZESax.js"),[]),path:"/apps/parcels",type:"mdx",filePath:"apps/parcels.mdx",content:"%23%20Parcels%0A%0AA%20minimal%20package%20tracking%20app%0A%0A%3A%3A%3Awarning%0AThis%20app%20originally%20used%20USPS%2C%20but%20starting%20April%201st%202026%2C%20it%20has%20become%20much%20harder%20to%20obtain%2Fmaintain%20API%20keys.%0A%3A%3A%3A%0A%0A%23%23%20Overview%0A%0AA%20self-hosted%20package%20tracker%20for%20USPS.%20Track%20your%20packages%20without%20logging%20into%20USPS%20every%20time.%0A%0A-%20Single%20~7MB%20Rust%20binary%0A-%20Averages%20around%20~10MB%20of%20RAM%20usage%0A-%20Password%20authentication%0A-%20Track%20USPS%20packages%20with%20custom%20labels%0A-%20Delete%20packages%20you%20no%20longer%20want%20to%20track%0A%0A%23%23%20Quickstart%0A%0A%60%60%60bash%0Agit%20clone%20https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fandromeda.git%0Acd%20andromeda%0Acp%20apps%2Fparcels%2F.env.example%20.env%0A%23%20Edit%20.env%20with%20your%20USPS%20API%20credentials%20and%20app%20password%0Acargo%20run%20-p%20parcels%0A%60%60%60%0A%0AYou'll%20need%20a%20%5BUSPS%20Web%20Tools%20API%5D(https%3A%2F%2Fdeveloper.usps.com)%20account%20to%20get%20your%20%60USPS_CLIENT_ID%60%20and%20%60USPS_CLIENT_SECRET%60.%0A%0A%23%23%23%20Environment%20Variables%0A%0A%7C%20Variable%20%7C%20Description%20%7C%20Default%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20%60APP_PASSWORD%60%20%7C%20Password%20for%20login%20authentication%20%7C%20*required*%20%7C%0A%7C%20%60PARCELS_DB_PATH%60%20%7C%20SQLite%20database%20file%20path%20%7C%20%60parcels.db%60%20%7C%0A%7C%20%60USPS_CLIENT_ID%60%20%7C%20USPS%20OAuth2%20client%20ID%20%7C%20*required*%20%7C%0A%7C%20%60USPS_CLIENT_SECRET%60%20%7C%20USPS%20OAuth2%20client%20secret%20%7C%20*required*%20%7C%0A%7C%20%60PORT%60%20%7C%20Server%20port%20%7C%20%603000%60%20%7C%0A%7C%20%60COOKIE_SECURE%60%20%7C%20Enable%20HTTPS-only%20cookies%20%7C%20%60false%60%20%7C%0A%0A%23%23%20Structure%0A%0A%60%60%60%0Aparcels%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20src%2F%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20main.rs%20%20%20%20%20%20%20%20%23%20Axum%20web%20server%2C%20routes%2C%20and%20app%20state%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20auth.rs%20%20%20%20%20%20%20%20%23%20Password%20verification%20and%20session%20management%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20db.rs%20%20%20%20%20%20%20%20%20%20%23%20SQLite%20database%20layer%20(packages%2C%20events%2C%20sessions)%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20usps.rs%20%20%20%20%20%20%20%20%23%20USPS%20API%20integration%20with%20OAuth2%20token%20caching%0A%E2%94%9C%E2%94%80%E2%94%80%20templates%2F%20%20%20%20%20%20%20%20%20%23%20Askama%20HTML%20templates%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20base.html%20%20%20%20%20%20%23%20Base%20layout%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20index.html%20%20%20%20%20%23%20Package%20list%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20detail.html%20%20%20%20%23%20Package%20detail%20with%20tracking%20events%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20add.html%20%20%20%20%20%20%20%23%20Add%20package%20form%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20login.html%20%20%20%20%20%23%20Login%20page%0A%E2%94%9C%E2%94%80%E2%94%80%20static%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Fonts%2C%20favicons%2C%20and%20images%0A%E2%94%9C%E2%94%80%E2%94%80%20Dockerfile%0A%E2%94%94%E2%94%80%E2%94%80%20docker-compose.yml%0A%60%60%60%0A%0A%23%23%20Deployment%0A%0A%23%23%23%20Railway%0A%0A%5B!%5BDeploy%20on%20Railway%5D(https%3A%2F%2Frailway.com%2Fbutton.svg)%5D(https%3A%2F%2Frailway.com%2Fdeploy%2FHNQUs4%3FreferralCode%3DJGcIp6)%0A%0A%23%23%23%20Docker%0A%0A%60%60%60bash%0Acd%20apps%2Fparcels%0Acp%20.env.example%20.env%0A%23%20Edit%20.env%20with%20your%20credentials%0Adocker%20compose%20up%20-d%0A%60%60%60%0A%0AThis%20will%20start%20Parcels%20on%20port%20%603000%60%20with%20a%20persistent%20volume%20for%20the%20SQLite%20database.%0A%0A%23%23%23%20Binary%0A%0A%60%60%60bash%0Acargo%20build%20--release%20-p%20parcels%0A%60%60%60%0A%0AThe%20resulting%20binary%20is%20self-contained%20(~7MB).%20Copy%20it%20to%20your%20server%20with%20a%20configured%20%60.env%60%20file%20and%20run%20it%20directly.%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./parcels-C9RZESax.js"),[]),path:"/apps/parcels.html",type:"mdx",filePath:"apps/parcels.mdx",content:"%23%20Parcels%0A%0AA%20minimal%20package%20tracking%20app%0A%0A%3A%3A%3Awarning%0AThis%20app%20originally%20used%20USPS%2C%20but%20starting%20April%201st%202026%2C%20it%20has%20become%20much%20harder%20to%20obtain%2Fmaintain%20API%20keys.%0A%3A%3A%3A%0A%0A%23%23%20Overview%0A%0AA%20self-hosted%20package%20tracker%20for%20USPS.%20Track%20your%20packages%20without%20logging%20into%20USPS%20every%20time.%0A%0A-%20Single%20~7MB%20Rust%20binary%0A-%20Averages%20around%20~10MB%20of%20RAM%20usage%0A-%20Password%20authentication%0A-%20Track%20USPS%20packages%20with%20custom%20labels%0A-%20Delete%20packages%20you%20no%20longer%20want%20to%20track%0A%0A%23%23%20Quickstart%0A%0A%60%60%60bash%0Agit%20clone%20https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fandromeda.git%0Acd%20andromeda%0Acp%20apps%2Fparcels%2F.env.example%20.env%0A%23%20Edit%20.env%20with%20your%20USPS%20API%20credentials%20and%20app%20password%0Acargo%20run%20-p%20parcels%0A%60%60%60%0A%0AYou'll%20need%20a%20%5BUSPS%20Web%20Tools%20API%5D(https%3A%2F%2Fdeveloper.usps.com)%20account%20to%20get%20your%20%60USPS_CLIENT_ID%60%20and%20%60USPS_CLIENT_SECRET%60.%0A%0A%23%23%23%20Environment%20Variables%0A%0A%7C%20Variable%20%7C%20Description%20%7C%20Default%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20%60APP_PASSWORD%60%20%7C%20Password%20for%20login%20authentication%20%7C%20*required*%20%7C%0A%7C%20%60PARCELS_DB_PATH%60%20%7C%20SQLite%20database%20file%20path%20%7C%20%60parcels.db%60%20%7C%0A%7C%20%60USPS_CLIENT_ID%60%20%7C%20USPS%20OAuth2%20client%20ID%20%7C%20*required*%20%7C%0A%7C%20%60USPS_CLIENT_SECRET%60%20%7C%20USPS%20OAuth2%20client%20secret%20%7C%20*required*%20%7C%0A%7C%20%60PORT%60%20%7C%20Server%20port%20%7C%20%603000%60%20%7C%0A%7C%20%60COOKIE_SECURE%60%20%7C%20Enable%20HTTPS-only%20cookies%20%7C%20%60false%60%20%7C%0A%0A%23%23%20Structure%0A%0A%60%60%60%0Aparcels%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20src%2F%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20main.rs%20%20%20%20%20%20%20%20%23%20Axum%20web%20server%2C%20routes%2C%20and%20app%20state%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20auth.rs%20%20%20%20%20%20%20%20%23%20Password%20verification%20and%20session%20management%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20db.rs%20%20%20%20%20%20%20%20%20%20%23%20SQLite%20database%20layer%20(packages%2C%20events%2C%20sessions)%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20usps.rs%20%20%20%20%20%20%20%20%23%20USPS%20API%20integration%20with%20OAuth2%20token%20caching%0A%E2%94%9C%E2%94%80%E2%94%80%20templates%2F%20%20%20%20%20%20%20%20%20%23%20Askama%20HTML%20templates%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20base.html%20%20%20%20%20%20%23%20Base%20layout%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20index.html%20%20%20%20%20%23%20Package%20list%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20detail.html%20%20%20%20%23%20Package%20detail%20with%20tracking%20events%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20add.html%20%20%20%20%20%20%20%23%20Add%20package%20form%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20login.html%20%20%20%20%20%23%20Login%20page%0A%E2%94%9C%E2%94%80%E2%94%80%20static%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Fonts%2C%20favicons%2C%20and%20images%0A%E2%94%9C%E2%94%80%E2%94%80%20Dockerfile%0A%E2%94%94%E2%94%80%E2%94%80%20docker-compose.yml%0A%60%60%60%0A%0A%23%23%20Deployment%0A%0A%23%23%23%20Railway%0A%0A%5B!%5BDeploy%20on%20Railway%5D(https%3A%2F%2Frailway.com%2Fbutton.svg)%5D(https%3A%2F%2Frailway.com%2Fdeploy%2FHNQUs4%3FreferralCode%3DJGcIp6)%0A%0A%23%23%23%20Docker%0A%0A%60%60%60bash%0Acd%20apps%2Fparcels%0Acp%20.env.example%20.env%0A%23%20Edit%20.env%20with%20your%20credentials%0Adocker%20compose%20up%20-d%0A%60%60%60%0A%0AThis%20will%20start%20Parcels%20on%20port%20%603000%60%20with%20a%20persistent%20volume%20for%20the%20SQLite%20database.%0A%0A%23%23%23%20Binary%0A%0A%60%60%60bash%0Acargo%20build%20--release%20-p%20parcels%0A%60%60%60%0A%0AThe%20resulting%20binary%20is%20self-contained%20(~7MB).%20Copy%20it%20to%20your%20server%20with%20a%20configured%20%60.env%60%20file%20and%20run%20it%20directly.%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./shrink-Ca22T4IR.js"),[]),path:"/apps/shrink",type:"mdx",filePath:"apps/shrink.mdx",content:"%23%20Shrink%0A%0AA%20minimal%20image%20compression%20app%0A%0A%23%23%20Overview%0A%0AA%20simple%20self-hosted%20tool%20for%20compressing%20and%20resizing%20images.%20Upload%20an%20image%2C%20set%20your%20desired%20quality%20and%20optional%20width%2C%20and%20download%20the%20compressed%20JPEG.%0A%0A-%20Single%20Rust%20binary%0A-%20Compress%20images%20to%20JPEG%20with%20configurable%20quality%20(1-100)%0A-%20Optional%20resize%20by%20width%20(preserves%20aspect%20ratio)%0A-%2020MB%20upload%20limit%0A%0A%23%23%20Quickstart%0A%0A%60%60%60bash%0Agit%20clone%20https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fandromeda.git%0Acd%20andromeda%0Acargo%20run%20-p%20shrink%0A%60%60%60%0A%0A%23%23%23%20Environment%20Variables%0A%0A%7C%20Variable%20%7C%20Description%20%7C%20Default%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20%60HOST%60%20%7C%20Server%20bind%20host%20%7C%20%60127.0.0.1%60%20%7C%0A%7C%20%60PORT%60%20%7C%20Server%20bind%20port%20%7C%20%603000%60%20%7C%0A%0A%23%23%20Structure%0A%0A%60%60%60%0Ashrink%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20src%2F%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20main.rs%20%20%20%20%20%20%20%20%23%20Entry%20point%20and%20server%20startup%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20server.rs%20%20%20%20%20%20%23%20Axum%20routes%20and%20image%20compression%20logic%0A%E2%94%9C%E2%94%80%E2%94%80%20templates%2F%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20index.html%20%20%20%20%20%23%20Upload%20UI%0A%E2%94%9C%E2%94%80%E2%94%80%20static%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Fonts%20and%20static%20assets%0A%E2%94%9C%E2%94%80%E2%94%80%20Dockerfile%0A%E2%94%94%E2%94%80%E2%94%80%20docker-compose.yml%0A%60%60%60%0A%0A%23%23%20Deployment%0A%0A%23%23%23%20Railway%0A%0A%5B!%5BDeploy%20on%20Railway%5D(https%3A%2F%2Frailway.com%2Fbutton.svg)%5D(https%3A%2F%2Frailway.com%2Fdeploy%2FenYUFb%3FreferralCode%3DJGcIp6)%0A%0A%23%23%23%20Docker%0A%0A%60%60%60bash%0Acd%20apps%2Fshrink%0Adocker%20compose%20up%20-d%0A%60%60%60%0A%0AThis%20will%20start%20Shrink%20on%20port%20%603000%60.%0A%0A%23%23%23%20Binary%0A%0A%60%60%60bash%0Acargo%20build%20--release%20-p%20shrink%0A%60%60%60%0A%0AThe%20resulting%20binary%20is%20self-contained.%20Copy%20it%20to%20your%20server%20and%20run%20it%20directly.%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./shrink-Ca22T4IR.js"),[]),path:"/apps/shrink.html",type:"mdx",filePath:"apps/shrink.mdx",content:"%23%20Shrink%0A%0AA%20minimal%20image%20compression%20app%0A%0A%23%23%20Overview%0A%0AA%20simple%20self-hosted%20tool%20for%20compressing%20and%20resizing%20images.%20Upload%20an%20image%2C%20set%20your%20desired%20quality%20and%20optional%20width%2C%20and%20download%20the%20compressed%20JPEG.%0A%0A-%20Single%20Rust%20binary%0A-%20Compress%20images%20to%20JPEG%20with%20configurable%20quality%20(1-100)%0A-%20Optional%20resize%20by%20width%20(preserves%20aspect%20ratio)%0A-%2020MB%20upload%20limit%0A%0A%23%23%20Quickstart%0A%0A%60%60%60bash%0Agit%20clone%20https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fandromeda.git%0Acd%20andromeda%0Acargo%20run%20-p%20shrink%0A%60%60%60%0A%0A%23%23%23%20Environment%20Variables%0A%0A%7C%20Variable%20%7C%20Description%20%7C%20Default%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20%60HOST%60%20%7C%20Server%20bind%20host%20%7C%20%60127.0.0.1%60%20%7C%0A%7C%20%60PORT%60%20%7C%20Server%20bind%20port%20%7C%20%603000%60%20%7C%0A%0A%23%23%20Structure%0A%0A%60%60%60%0Ashrink%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20src%2F%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20main.rs%20%20%20%20%20%20%20%20%23%20Entry%20point%20and%20server%20startup%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20server.rs%20%20%20%20%20%20%23%20Axum%20routes%20and%20image%20compression%20logic%0A%E2%94%9C%E2%94%80%E2%94%80%20templates%2F%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20index.html%20%20%20%20%20%23%20Upload%20UI%0A%E2%94%9C%E2%94%80%E2%94%80%20static%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Fonts%20and%20static%20assets%0A%E2%94%9C%E2%94%80%E2%94%80%20Dockerfile%0A%E2%94%94%E2%94%80%E2%94%80%20docker-compose.yml%0A%60%60%60%0A%0A%23%23%20Deployment%0A%0A%23%23%23%20Railway%0A%0A%5B!%5BDeploy%20on%20Railway%5D(https%3A%2F%2Frailway.com%2Fbutton.svg)%5D(https%3A%2F%2Frailway.com%2Fdeploy%2FenYUFb%3FreferralCode%3DJGcIp6)%0A%0A%23%23%23%20Docker%0A%0A%60%60%60bash%0Acd%20apps%2Fshrink%0Adocker%20compose%20up%20-d%0A%60%60%60%0A%0AThis%20will%20start%20Shrink%20on%20port%20%603000%60.%0A%0A%23%23%23%20Binary%0A%0A%60%60%60bash%0Acargo%20build%20--release%20-p%20shrink%0A%60%60%60%0A%0AThe%20resulting%20binary%20is%20self-contained.%20Copy%20it%20to%20your%20server%20and%20run%20it%20directly.%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./sipp-DSSVP1iR.js"),[]),path:"/apps/sipp",type:"mdx",filePath:"apps/sipp.mdx",content:"%23%20Sipp%0A%0AMinimal%20code%20sharing%0A%0A%23%23%20Overview%0A%0AA%20single%20binary%20for%20code%20sharing%20with%20a%20web%20server%20and%20interactive%20TUI.%0A%0A-%20Create%20snippets%20and%20share%20on%20the%20web%0A-%20Raw%20output%20for%20CLI%20tools%20--%20%60curl%60%2C%20%60wget%60%2C%20and%20%60httpie%60%20get%20plain%20text%20automatically%0A-%20Interactive%20TUI%20with%20authenticated%20access%20for%20snippet%20management%0A-%20Minimal%2C%20fast%2C%20and%20low%20memory%20consumption%0A%0A%3A%3A%3Awarning%0AA%20small%20demo%20instance%20runs%20at%20%5Bsipp.so%5D(https%3A%2F%2Fsipp.so).%20All%20snippets%20created%20there%20are%20public%20and%20might%20be%20deleted%20at%20any%20time%3B%20host%20your%20own%20instance%20with%20your%20own%20API%20key%20for%20personal%20use!%0A%3A%3A%3A%0A%0A%23%23%20Quickstart%0A%0A%60%60%60bash%0Acargo%20install%20sipp-so%0Asipp%20--help%0A%60%60%60%0A%0AStart%20a%20server%20and%20create%20a%20snippet%3A%0A%0A%60%60%60bash%0Asipp%20server%20--port%203000%0A%60%60%60%0A%0A%60%60%60bash%0A%23%20Path%20to%20file%0Asipp%20path%2Fto%2Ffile.rs%0A%0A%23%20Or%20use%20the%20interactive%20TUI%0Asipp%0A%60%60%60%0A%0A%23%23%23%20Install%0A%0ASipp%20can%20be%20installed%20several%20ways%3A%0A%0A%23%23%23%23%20Homebrew%0A%0A%60%60%60bash%0Abrew%20install%20stevedylandev%2Ftap%2Fsipp-so%0A%60%60%60%0A%0A%23%23%23%23%20Cargo%0A%0A%60%60%60bash%0Acargo%20install%20sipp-so%0A%60%60%60%0A%0A%23%23%23%23%20Releases%0A%0AVisit%20the%20%5Breleases%5D(https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fsipp%2Freleases)%20page%20for%20binaries%20and%20install%20scripts.%0A%0A%23%23%20CLI%0A%0A%60%60%60%0Asipp%20%5BOPTIONS%5D%20%5BFILE%5D%20%5BCOMMAND%5D%0A%60%60%60%0A%0A%23%23%23%20Commands%0A%0A%7C%20Command%20%7C%20Description%20%7C%0A%7C---%7C---%7C%0A%7C%20%60server%60%20%7C%20Start%20the%20web%20server%20%7C%0A%7C%20%60tui%60%20%7C%20Launch%20the%20interactive%20TUI%20%7C%0A%7C%20%60auth%60%20%7C%20Save%20remote%20URL%20and%20API%20key%20to%20config%20file%20%7C%0A%0A%23%23%23%20Arguments%0A%0A%7C%20Argument%20%7C%20Description%20%7C%0A%7C---%7C---%7C%0A%7C%20%60%5BFILE%5D%60%20%7C%20File%20path%20to%20create%20a%20snippet%20from%20%7C%0A%0A%23%23%23%20Options%0A%0A%7C%20Option%20%7C%20Description%20%7C%0A%7C---%7C---%7C%0A%7C%20%60-r%2C%20--remote%20%3CURL%3E%60%20%7C%20Remote%20server%20URL%20(env%3A%20%60SIPP_REMOTE_URL%60)%20%7C%0A%7C%20%60-k%2C%20--api-key%20%3CKEY%3E%60%20%7C%20API%20key%20for%20authenticated%20operations%20(env%3A%20%60SIPP_API_KEY%60)%20%7C%0A%0A%23%23%20Server%0A%0ASipp%20includes%20a%20built-in%20web%20server%20powered%20by%20Axum.%20Start%20it%20with%3A%0A%0A%60%60%60bash%0Asipp%20server%20--port%203000%20--host%20localhost%0A%60%60%60%0A%0A%23%23%23%20Environment%20Variables%0A%0A%7C%20Variable%20%7C%20Description%20%7C%0A%7C---%7C---%7C%0A%7C%20%60SIPP_API_KEY%60%20%7C%20API%20key%20for%20protecting%20endpoints%20%7C%0A%7C%20%60SIPP_AUTH_ENDPOINTS%60%20%7C%20Comma-separated%20list%20of%20endpoints%20requiring%20auth%3A%20%60api_list%60%2C%20%60api_create%60%2C%20%60api_get%60%2C%20%60api_delete%60%2C%20%60all%60%2C%20or%20%60none%60%20(defaults%20to%20%60api_delete%2Capi_list%60)%20%7C%0A%7C%20%60SIPP_MAX_CONTENT_SIZE%60%20%7C%20Maximum%20snippet%20content%20size%20in%20bytes%20(defaults%20to%20%60512000%60%20%2F%20500%20KB)%20%7C%0A%7C%20%60SIPP_DB_PATH%60%20%7C%20Custom%20path%20for%20the%20SQLite%20database%20file%20(defaults%20to%20%60sipp.sqlite%60)%20%7C%0A%0A%23%23%23%20API%20Endpoints%0A%0A%7C%20Method%20%7C%20Endpoint%20%7C%20Description%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20%60GET%60%20%7C%20%60%2Fapi%2Fsnippets%60%20%7C%20List%20all%20snippets%20%7C%0A%7C%20%60POST%60%20%7C%20%60%2Fapi%2Fsnippets%60%20%7C%20Create%20a%20snippet%20(%60%7B%22name%22%3A%20%22...%22%2C%20%22content%22%3A%20%22...%22%7D%60)%20%7C%0A%7C%20%60GET%60%20%7C%20%60%2Fapi%2Fsnippets%2F%7Bshort_id%7D%60%20%7C%20Get%20a%20snippet%20by%20ID%20%7C%0A%7C%20%60PUT%60%20%7C%20%60%2Fapi%2Fsnippets%2F%7Bshort_id%7D%60%20%7C%20Update%20a%20snippet%20%7C%0A%7C%20%60DELETE%60%20%7C%20%60%2Fapi%2Fsnippets%2F%7Bshort_id%7D%60%20%7C%20Delete%20a%20snippet%20by%20ID%20%7C%0A%0AAuthenticated%20endpoints%20require%20an%20%60x-api-key%60%20header.%0A%0A%23%23%23%20Raw%20Output%20for%20CLI%20Tools%0A%0AWhen%20you%20access%20a%20snippet%20URL%20(%60%2Fs%2F%7Bshort_id%7D%60)%20with%20%60curl%60%2C%20%60wget%60%2C%20or%20%60httpie%60%2C%20the%20server%20returns%20the%20raw%20content%20as%20plain%20text%20instead%20of%20HTML%3A%0A%0A%60%60%60bash%0Acurl%20https%3A%2F%2Fsipp.so%2Fs%2Fabc123%0A%60%60%60%0A%0A%23%23%20TUI%0A%0AThe%20Sipp%20TUI%20makes%20it%20easy%20to%20create%2C%20copy%2C%20share%2C%20and%20manage%20your%20snippets%20either%20locally%20or%20remotely.%0A%0A%60%60%60bash%0A%23%20Launch%20TUI%20(default%20behavior%20when%20no%20file%20argument%20is%20given)%0Asipp%0A%0A%23%20Or%20explicitly%0Asipp%20tui%0A%0A%23%20With%20remote%20options%0Asipp%20-r%20https%3A%2F%2Fsipp.so%20-k%20your-api-key%0A%60%60%60%0A%0A%23%23%23%20Local%20Access%0A%0AIf%20you%20are%20running%20%60sipp%60%20in%20the%20same%20directory%20as%20the%20%60sipp.sqlite%60%20file%20created%20by%20the%20server%20instance%2C%20the%20TUI%20will%20automatically%20access%20the%20database%20locally.%0A%0A%23%23%23%20Remote%20Access%0A%0ATo%20access%20a%20remote%20instance%3A%0A-%20Set%20the%20%60SIPP_API_KEY%60%20variable%20in%20your%20server%20instance%0A-%20Run%20%60sipp%20auth%60%20to%20enter%20your%20server%20URL%20and%20API%20key%2C%20stored%20under%20%60%24HOME%2F.config%2Fsipp%60%0A%0A%23%23%23%20Keybindings%0A%0A%7C%20Key%20%7C%20Action%20%7C%0A%7C---%7C---%7C%0A%7C%20%60j%60%2F%60Down%60%20%7C%20Move%20down%20%2F%20Scroll%20down%20%7C%0A%7C%20%60k%60%2F%60Up%60%20%7C%20Move%20up%20%2F%20Scroll%20up%20%7C%0A%7C%20%60Enter%60%20%7C%20Focus%20content%20pane%20%7C%0A%7C%20%60Esc%60%20%7C%20Back%20%2F%20Quit%20%7C%0A%7C%20%60y%60%20%7C%20Copy%20snippet%20content%20%7C%0A%7C%20%60Y%60%20%7C%20Copy%20snippet%20link%20%7C%0A%7C%20%60o%60%20%7C%20Open%20in%20browser%20%7C%0A%7C%20%60e%60%20%7C%20Edit%20snippet%20%7C%0A%7C%20%60d%60%20%7C%20Delete%20snippet%20%7C%0A%7C%20%60c%60%20%7C%20Create%20snippet%20%7C%0A%7C%20%60%2F%60%20%7C%20Search%20snippets%20%7C%0A%7C%20%60r%60%20%7C%20Refresh%20snippets%20(remote%20only)%20%7C%0A%7C%20%60q%60%20%7C%20Quit%20%7C%0A%7C%20%60%3F%60%20%7C%20Toggle%20help%20%7C%0A%0A%23%23%20Structure%0A%0A%60%60%60%0Asipp%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20src%2F%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20main.rs%20%20%20%20%20%20%20%20%23%20CLI%20argument%20parsing%20and%20entry%20point%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20lib.rs%20%20%20%20%20%20%20%20%20%23%20Library%20exports%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20server.rs%20%20%20%20%20%20%23%20Axum%20web%20server%2C%20routes%2C%20and%20templates%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20tui.rs%20%20%20%20%20%20%20%20%20%23%20Interactive%20terminal%20UI%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20db.rs%20%20%20%20%20%20%20%20%20%20%23%20SQLite%20database%20layer%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20backend.rs%20%20%20%20%20%23%20Local%2Fremote%20backend%20abstraction%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20config.rs%20%20%20%20%20%20%23%20Config%20file%20management%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20highlight.rs%20%20%20%23%20Syntax%20highlighting%20with%20custom%20themes%0A%E2%94%9C%E2%94%80%E2%94%80%20templates%2F%20%20%20%20%20%20%20%20%20%23%20Askama%20HTML%20templates%0A%E2%94%9C%E2%94%80%E2%94%80%20static%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Fonts%2C%20favicons%2C%20and%20styles%0A%E2%94%9C%E2%94%80%E2%94%80%20Dockerfile%0A%E2%94%94%E2%94%80%E2%94%80%20docker-compose.yml%0A%60%60%60%0A%0A%23%23%20Deployment%0A%0A%23%23%23%20Railway%0A%0A%5B!%5BDeploy%20on%20Railway%5D(https%3A%2F%2Frailway.com%2Fbutton.svg)%5D(https%3A%2F%2Frailway.com%2Fdeploy%2FAxcf_D%3FreferralCode%3DJGcIp6)%0A%0A%23%23%23%20Docker%0A%0A%60%60%60bash%0ASIPP_API_KEY%3Dyour-secret-key%20docker%20compose%20up%20-d%0A%60%60%60%0A%0A%23%23%23%20Binary%0A%0A%60%60%60bash%0Acargo%20build%20--release%20-p%20sipp%0A%60%60%60%0A%0AThe%20resulting%20binary%20is%20self-contained%20with%20all%20assets%20embedded.%20Copy%20it%20to%20your%20server%20with%20your%20environment%20variables%20configured%20and%20run%20it%20directly.%0A",lastUpdatedAt:1775649699e3},{lazy:()=>Ft(()=>import("./sipp-DSSVP1iR.js"),[]),path:"/apps/sipp.html",type:"mdx",filePath:"apps/sipp.mdx",content:"%23%20Sipp%0A%0AMinimal%20code%20sharing%0A%0A%23%23%20Overview%0A%0AA%20single%20binary%20for%20code%20sharing%20with%20a%20web%20server%20and%20interactive%20TUI.%0A%0A-%20Create%20snippets%20and%20share%20on%20the%20web%0A-%20Raw%20output%20for%20CLI%20tools%20--%20%60curl%60%2C%20%60wget%60%2C%20and%20%60httpie%60%20get%20plain%20text%20automatically%0A-%20Interactive%20TUI%20with%20authenticated%20access%20for%20snippet%20management%0A-%20Minimal%2C%20fast%2C%20and%20low%20memory%20consumption%0A%0A%3A%3A%3Awarning%0AA%20small%20demo%20instance%20runs%20at%20%5Bsipp.so%5D(https%3A%2F%2Fsipp.so).%20All%20snippets%20created%20there%20are%20public%20and%20might%20be%20deleted%20at%20any%20time%3B%20host%20your%20own%20instance%20with%20your%20own%20API%20key%20for%20personal%20use!%0A%3A%3A%3A%0A%0A%23%23%20Quickstart%0A%0A%60%60%60bash%0Acargo%20install%20sipp-so%0Asipp%20--help%0A%60%60%60%0A%0AStart%20a%20server%20and%20create%20a%20snippet%3A%0A%0A%60%60%60bash%0Asipp%20server%20--port%203000%0A%60%60%60%0A%0A%60%60%60bash%0A%23%20Path%20to%20file%0Asipp%20path%2Fto%2Ffile.rs%0A%0A%23%20Or%20use%20the%20interactive%20TUI%0Asipp%0A%60%60%60%0A%0A%23%23%23%20Install%0A%0ASipp%20can%20be%20installed%20several%20ways%3A%0A%0A%23%23%23%23%20Homebrew%0A%0A%60%60%60bash%0Abrew%20install%20stevedylandev%2Ftap%2Fsipp-so%0A%60%60%60%0A%0A%23%23%23%23%20Cargo%0A%0A%60%60%60bash%0Acargo%20install%20sipp-so%0A%60%60%60%0A%0A%23%23%23%23%20Releases%0A%0AVisit%20the%20%5Breleases%5D(https%3A%2F%2Fgithub.com%2Fstevedylandev%2Fsipp%2Freleases)%20page%20for%20binaries%20and%20install%20scripts.%0A%0A%23%23%20CLI%0A%0A%60%60%60%0Asipp%20%5BOPTIONS%5D%20%5BFILE%5D%20%5BCOMMAND%5D%0A%60%60%60%0A%0A%23%23%23%20Commands%0A%0A%7C%20Command%20%7C%20Description%20%7C%0A%7C---%7C---%7C%0A%7C%20%60server%60%20%7C%20Start%20the%20web%20server%20%7C%0A%7C%20%60tui%60%20%7C%20Launch%20the%20interactive%20TUI%20%7C%0A%7C%20%60auth%60%20%7C%20Save%20remote%20URL%20and%20API%20key%20to%20config%20file%20%7C%0A%0A%23%23%23%20Arguments%0A%0A%7C%20Argument%20%7C%20Description%20%7C%0A%7C---%7C---%7C%0A%7C%20%60%5BFILE%5D%60%20%7C%20File%20path%20to%20create%20a%20snippet%20from%20%7C%0A%0A%23%23%23%20Options%0A%0A%7C%20Option%20%7C%20Description%20%7C%0A%7C---%7C---%7C%0A%7C%20%60-r%2C%20--remote%20%3CURL%3E%60%20%7C%20Remote%20server%20URL%20(env%3A%20%60SIPP_REMOTE_URL%60)%20%7C%0A%7C%20%60-k%2C%20--api-key%20%3CKEY%3E%60%20%7C%20API%20key%20for%20authenticated%20operations%20(env%3A%20%60SIPP_API_KEY%60)%20%7C%0A%0A%23%23%20Server%0A%0ASipp%20includes%20a%20built-in%20web%20server%20powered%20by%20Axum.%20Start%20it%20with%3A%0A%0A%60%60%60bash%0Asipp%20server%20--port%203000%20--host%20localhost%0A%60%60%60%0A%0A%23%23%23%20Environment%20Variables%0A%0A%7C%20Variable%20%7C%20Description%20%7C%0A%7C---%7C---%7C%0A%7C%20%60SIPP_API_KEY%60%20%7C%20API%20key%20for%20protecting%20endpoints%20%7C%0A%7C%20%60SIPP_AUTH_ENDPOINTS%60%20%7C%20Comma-separated%20list%20of%20endpoints%20requiring%20auth%3A%20%60api_list%60%2C%20%60api_create%60%2C%20%60api_get%60%2C%20%60api_delete%60%2C%20%60all%60%2C%20or%20%60none%60%20(defaults%20to%20%60api_delete%2Capi_list%60)%20%7C%0A%7C%20%60SIPP_MAX_CONTENT_SIZE%60%20%7C%20Maximum%20snippet%20content%20size%20in%20bytes%20(defaults%20to%20%60512000%60%20%2F%20500%20KB)%20%7C%0A%7C%20%60SIPP_DB_PATH%60%20%7C%20Custom%20path%20for%20the%20SQLite%20database%20file%20(defaults%20to%20%60sipp.sqlite%60)%20%7C%0A%0A%23%23%23%20API%20Endpoints%0A%0A%7C%20Method%20%7C%20Endpoint%20%7C%20Description%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20%60GET%60%20%7C%20%60%2Fapi%2Fsnippets%60%20%7C%20List%20all%20snippets%20%7C%0A%7C%20%60POST%60%20%7C%20%60%2Fapi%2Fsnippets%60%20%7C%20Create%20a%20snippet%20(%60%7B%22name%22%3A%20%22...%22%2C%20%22content%22%3A%20%22...%22%7D%60)%20%7C%0A%7C%20%60GET%60%20%7C%20%60%2Fapi%2Fsnippets%2F%7Bshort_id%7D%60%20%7C%20Get%20a%20snippet%20by%20ID%20%7C%0A%7C%20%60PUT%60%20%7C%20%60%2Fapi%2Fsnippets%2F%7Bshort_id%7D%60%20%7C%20Update%20a%20snippet%20%7C%0A%7C%20%60DELETE%60%20%7C%20%60%2Fapi%2Fsnippets%2F%7Bshort_id%7D%60%20%7C%20Delete%20a%20snippet%20by%20ID%20%7C%0A%0AAuthenticated%20endpoints%20require%20an%20%60x-api-key%60%20header.%0A%0A%23%23%23%20Raw%20Output%20for%20CLI%20Tools%0A%0AWhen%20you%20access%20a%20snippet%20URL%20(%60%2Fs%2F%7Bshort_id%7D%60)%20with%20%60curl%60%2C%20%60wget%60%2C%20or%20%60httpie%60%2C%20the%20server%20returns%20the%20raw%20content%20as%20plain%20text%20instead%20of%20HTML%3A%0A%0A%60%60%60bash%0Acurl%20https%3A%2F%2Fsipp.so%2Fs%2Fabc123%0A%60%60%60%0A%0A%23%23%20TUI%0A%0AThe%20Sipp%20TUI%20makes%20it%20easy%20to%20create%2C%20copy%2C%20share%2C%20and%20manage%20your%20snippets%20either%20locally%20or%20remotely.%0A%0A%60%60%60bash%0A%23%20Launch%20TUI%20(default%20behavior%20when%20no%20file%20argument%20is%20given)%0Asipp%0A%0A%23%20Or%20explicitly%0Asipp%20tui%0A%0A%23%20With%20remote%20options%0Asipp%20-r%20https%3A%2F%2Fsipp.so%20-k%20your-api-key%0A%60%60%60%0A%0A%23%23%23%20Local%20Access%0A%0AIf%20you%20are%20running%20%60sipp%60%20in%20the%20same%20directory%20as%20the%20%60sipp.sqlite%60%20file%20created%20by%20the%20server%20instance%2C%20the%20TUI%20will%20automatically%20access%20the%20database%20locally.%0A%0A%23%23%23%20Remote%20Access%0A%0ATo%20access%20a%20remote%20instance%3A%0A-%20Set%20the%20%60SIPP_API_KEY%60%20variable%20in%20your%20server%20instance%0A-%20Run%20%60sipp%20auth%60%20to%20enter%20your%20server%20URL%20and%20API%20key%2C%20stored%20under%20%60%24HOME%2F.config%2Fsipp%60%0A%0A%23%23%23%20Keybindings%0A%0A%7C%20Key%20%7C%20Action%20%7C%0A%7C---%7C---%7C%0A%7C%20%60j%60%2F%60Down%60%20%7C%20Move%20down%20%2F%20Scroll%20down%20%7C%0A%7C%20%60k%60%2F%60Up%60%20%7C%20Move%20up%20%2F%20Scroll%20up%20%7C%0A%7C%20%60Enter%60%20%7C%20Focus%20content%20pane%20%7C%0A%7C%20%60Esc%60%20%7C%20Back%20%2F%20Quit%20%7C%0A%7C%20%60y%60%20%7C%20Copy%20snippet%20content%20%7C%0A%7C%20%60Y%60%20%7C%20Copy%20snippet%20link%20%7C%0A%7C%20%60o%60%20%7C%20Open%20in%20browser%20%7C%0A%7C%20%60e%60%20%7C%20Edit%20snippet%20%7C%0A%7C%20%60d%60%20%7C%20Delete%20snippet%20%7C%0A%7C%20%60c%60%20%7C%20Create%20snippet%20%7C%0A%7C%20%60%2F%60%20%7C%20Search%20snippets%20%7C%0A%7C%20%60r%60%20%7C%20Refresh%20snippets%20(remote%20only)%20%7C%0A%7C%20%60q%60%20%7C%20Quit%20%7C%0A%7C%20%60%3F%60%20%7C%20Toggle%20help%20%7C%0A%0A%23%23%20Structure%0A%0A%60%60%60%0Asipp%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20src%2F%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20main.rs%20%20%20%20%20%20%20%20%23%20CLI%20argument%20parsing%20and%20entry%20point%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20lib.rs%20%20%20%20%20%20%20%20%20%23%20Library%20exports%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20server.rs%20%20%20%20%20%20%23%20Axum%20web%20server%2C%20routes%2C%20and%20templates%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20tui.rs%20%20%20%20%20%20%20%20%20%23%20Interactive%20terminal%20UI%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20db.rs%20%20%20%20%20%20%20%20%20%20%23%20SQLite%20database%20layer%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20backend.rs%20%20%20%20%20%23%20Local%2Fremote%20backend%20abstraction%0A%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20config.rs%20%20%20%20%20%20%23%20Config%20file%20management%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20highlight.rs%20%20%20%23%20Syntax%20highlighting%20with%20custom%20themes%0A%E2%94%9C%E2%94%80%E2%94%80%20templates%2F%20%20%20%20%20%20%20%20%20%23%20Askama%20HTML%20templates%0A%E2%94%9C%E2%94%80%E2%94%80%20static%2F%20%20%20%20%20%20%20%20%20%20%20%20%23%20Fonts%2C%20favicons%2C%20and%20styles%0A%E2%94%9C%E2%94%80%E2%94%80%20Dockerfile%0A%E2%94%94%E2%94%80%E2%94%80%20docker-compose.yml%0A%60%60%60%0A%0A%23%23%20Deployment%0A%0A%23%23%23%20Railway%0A%0A%5B!%5BDeploy%20on%20Railway%5D(https%3A%2F%2Frailway.com%2Fbutton.svg)%5D(https%3A%2F%2Frailway.com%2Fdeploy%2FAxcf_D%3FreferralCode%3DJGcIp6)%0A%0A%23%23%23%20Docker%0A%0A%60%60%60bash%0ASIPP_API_KEY%3Dyour-secret-key%20docker%20compose%20up%20-d%0A%60%60%60%0A%0A%23%23%23%20Binary%0A%0A%60%60%60bash%0Acargo%20build%20--release%20-p%20sipp%0A%60%60%60%0A%0AThe%20resulting%20binary%20is%20self-contained%20with%20all%20assets%20embedded.%20Copy%20it%20to%20your%20server%20with%20your%20environment%20variables%20configured%20and%20run%20it%20directly.%0A",lastUpdatedAt:1775649699e3}];var _f={background5:"var(--vocs-color_background5)",border:"var(--vocs-color_border)",border2:"var(--vocs-color_border2)"},jg={default:"system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif",mono:'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace'},Fg={default:"var(--vocs-fontFamily_default)",mono:"var(--vocs-fontFamily_mono)"},ml={4:"var(--vocs-space_4)",8:"var(--vocs-space_8)",24:"var(--vocs-space_24)"},L2={horizontalPadding:"var(--vocs-content_horizontalPadding)",verticalPadding:"var(--vocs-content_verticalPadding)",width:"var(--vocs-content_width)"};function Vy(t){var a,o,i="";if(typeof t=="string"||typeof t=="number")i+=t;else if(typeof t=="object")if(Array.isArray(t)){var s=t.length;for(a=0;a<s;a++)t[a]&&(o=Vy(t[a]))&&(i&&(i+=" "),i+=o)}else for(o in t)t[o]&&(i&&(i+=" "),i+=o);return i}function me(){for(var t,a,o=0,i="",s=arguments.length;o<s;o++)(t=arguments[o])&&(a=Vy(t))&&(i&&(i+=" "),i+=a);return i}function Z7(t){var a=t.match(/^var\((.*)\)$/);return a?a[1]:t}function aa(t,a){var o={};{var i=t;for(var s in i){var u=i[s];u!=null&&(o[Z7(s)]=u)}}return Object.defineProperty(o,"toString",{value:function(){return Object.keys(this).map(d=>"".concat(d,":").concat(this[d])).join(";")},writable:!1}),o}var J7="var(--vocs_ExternalLink_iconUrl)",W7="vocs_ExternalLink";const e8=y.forwardRef(({className:t,children:a,hideExternalIcon:o,href:i,...s},u)=>{const{basePath:c}=Ot(),d=c;return g.jsx("a",{ref:u,className:me(t,o||typeof a!="string"?void 0:W7),href:i,target:"_blank",rel:"noopener noreferrer",style:aa({[J7]:`url(${d}/.vocs/icons/arrow-diagonal.svg)`}),...s,children:a})});var kg="vocs_Link",zg="vocs_Link_accent",Ug="vocs_Link_styleless",Rf=new Map,nu=new WeakMap,Pg=0,t8=void 0;function n8(t){return t?(nu.has(t)||(Pg+=1,nu.set(t,Pg.toString())),nu.get(t)):"0"}function a8(t){return Object.keys(t).sort().filter(a=>t[a]!==void 0).map(a=>`${a}_${a==="root"?n8(t.root):t[a]}`).toString()}function r8(t){const a=a8(t);let o=Rf.get(a);if(!o){const i=new Map;let s;const u=new IntersectionObserver(c=>{c.forEach(d=>{var v;const m=d.isIntersecting&&s.some(A=>d.intersectionRatio>=A);t.trackVisibility&&typeof d.isVisible>"u"&&(d.isVisible=m),(v=i.get(d.target))==null||v.forEach(A=>{A(m,d)})})},t);s=u.thresholds||(Array.isArray(t.threshold)?t.threshold:[t.threshold||0]),o={id:a,observer:u,elements:i},Rf.set(a,o)}return o}function o8(t,a,o={},i=t8){if(typeof window.IntersectionObserver>"u"&&i!==void 0){const v=t.getBoundingClientRect();return a(i,{isIntersecting:i,target:t,intersectionRatio:typeof o.threshold=="number"?o.threshold:0,time:0,boundingClientRect:v,intersectionRect:v,rootBounds:v}),()=>{}}const{id:s,observer:u,elements:c}=r8(o),d=c.get(t)||[];return c.has(t)||c.set(t,d),d.push(a),u.observe(t),function(){d.splice(d.indexOf(a),1),d.length===0&&(c.delete(t),u.unobserve(t)),c.size===0&&(u.disconnect(),Rf.delete(s))}}function qy({threshold:t,delay:a,trackVisibility:o,rootMargin:i,root:s,triggerOnce:u,skip:c,initialInView:d,fallbackInView:v,onChange:m}={}){var A;const[p,C]=y.useState(null),b=y.useRef(m),[S,x]=y.useState({inView:!!d,entry:void 0});b.current=m,y.useEffect(()=>{if(c||!p)return;let R;return R=o8(p,(_,N)=>{x({inView:_,entry:N}),b.current&&b.current(_,N),N.isIntersecting&&u&&R&&(R(),R=void 0)},{root:s,rootMargin:i,threshold:t,trackVisibility:o,delay:a},v),()=>{R&&R()}},[Array.isArray(t)?t.toString():t,p,s,i,u,c,o,v,a]);const w=(A=S.entry)==null?void 0:A.target,D=y.useRef(void 0);!p&&w&&!u&&!c&&D.current!==w&&(D.current=w,x({inView:!!d,entry:void 0}));const T=[C,S.inView,S.entry];return T.ref=T[0],T.inView=T[1],T.entry=T[2],T}function i8(...t){return a=>{l8(a,...t)}}function l8(t,...a){a.forEach(o=>{typeof o=="function"?o(t):o!=null&&(o.current=t)})}const ni=y.forwardRef((t,a)=>{const o=()=>md.find(u=>u.path===t.to)?.lazy(),{ref:i,inView:s}=qy();return y.useEffect(()=>{s&&o()},[s,o]),g.jsx(ci,{ref:i8(a,i),...t})}),qn=y.forwardRef((t,a)=>{const{hideExternalIcon:o,href:i,variant:s="accent",...u}=t,{pathname:c}=ft();if(i?.match(/^(www|https?)/))return g.jsx(e8,{ref:a,className:me(t.className,kg,s==="accent"&&zg,s==="styleless"&&Ug),hideExternalIcon:o,href:i,...u});const[d,v]=(i||"").split("#"),m=`${d||c}${v?`#${v}`:""}`;return g.jsx(ni,{...u,ref:a,className:me(t.className,kg,s==="accent"&&zg,s==="styleless"&&Ug),to:m})});var s8="vocs_H1",Gy="vocs_Heading",Yy="vocs_Heading_slugTarget";function fi({level:t,...a}){const o=`h${t}`;return g.jsxs(o,{...a,id:void 0,className:me(a.className,Gy),children:[g.jsx("div",{id:a.id,className:Yy}),a.children]})}function Qy(t){return g.jsx(fi,{...t,className:me(t.className,s8),level:1})}var u8="vocs_Paragraph";function Ky(t){return g.jsx("p",{...t,className:me(t.className,u8)})}var c8="vocs_NotFound",f8="vocs_NotFound_divider";function d8(){return g.jsxs("div",{className:c8,children:[g.jsx(Qy,{children:"Page Not Found"}),g.jsx("div",{style:{height:ml[24]}}),g.jsx("hr",{className:f8}),g.jsx("div",{style:{height:ml[24]}}),g.jsx(Ky,{children:"The page you were looking for could not be found."}),g.jsx("div",{style:{height:ml[8]}}),g.jsx(qn,{href:"/",children:"Go to Home Page"})]})}var h8="var(--vocs_Banner_bannerBackgroundColor)",p8="var(--vocs_Banner_bannerHeight)",m8="var(--vocs_Banner_bannerTextColor)",v8="vocs_Banner",g8="vocs_Banner_content",y8="vocs_Banner_inner",A8="vocs_Banner_closeButton";const C8=Object.getPrototypeOf(b8).constructor;async function b8(t,a){return new C8(String(t))(a)}function E8(t,a){return new Function(String(t))(a)}function ao(t,a){if(t==null)return{};var o={},i=Object.keys(t),s,u;for(u=0;u<i.length;u++)s=i[u],!(a.indexOf(s)>=0)&&(o[s]=t[s]);return o}var S8=["color"],x8=y.forwardRef(function(t,a){var o=t.color,i=o===void 0?"currentColor":o,s=ao(t,S8);return y.createElement("svg",Object.assign({width:"15",height:"15",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},s,{ref:a}),y.createElement("path",{d:"M6.85355 3.14645C7.04882 3.34171 7.04882 3.65829 6.85355 3.85355L3.70711 7H12.5C12.7761 7 13 7.22386 13 7.5C13 7.77614 12.7761 8 12.5 8H3.70711L6.85355 11.1464C7.04882 11.3417 7.04882 11.6583 6.85355 11.8536C6.65829 12.0488 6.34171 12.0488 6.14645 11.8536L2.14645 7.85355C1.95118 7.65829 1.95118 7.34171 2.14645 7.14645L6.14645 3.14645C6.34171 2.95118 6.65829 2.95118 6.85355 3.14645Z",fill:i,fillRule:"evenodd",clipRule:"evenodd"}))}),w8=["color"],_8=y.forwardRef(function(t,a){var o=t.color,i=o===void 0?"currentColor":o,s=ao(t,w8);return y.createElement("svg",Object.assign({width:"15",height:"15",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},s,{ref:a}),y.createElement("path",{d:"M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z",fill:i,fillRule:"evenodd",clipRule:"evenodd"}))}),R8=["color"],T8=y.forwardRef(function(t,a){var o=t.color,i=o===void 0?"currentColor":o,s=ao(t,R8);return y.createElement("svg",Object.assign({width:"15",height:"15",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},s,{ref:a}),y.createElement("path",{d:"M12.8536 2.85355C13.0488 2.65829 13.0488 2.34171 12.8536 2.14645C12.6583 1.95118 12.3417 1.95118 12.1464 2.14645L7.5 6.79289L2.85355 2.14645C2.65829 1.95118 2.34171 1.95118 2.14645 2.14645C1.95118 2.34171 1.95118 2.65829 2.14645 2.85355L6.79289 7.5L2.14645 12.1464C1.95118 12.3417 1.95118 12.6583 2.14645 12.8536C2.34171 13.0488 2.65829 13.0488 2.85355 12.8536L7.5 8.20711L12.1464 12.8536C12.3417 13.0488 12.6583 13.0488 12.8536 12.8536C13.0488 12.6583 13.0488 12.3417 12.8536 12.1464L8.20711 7.5L12.8536 2.85355Z",fill:i,fillRule:"evenodd",clipRule:"evenodd"}))}),M8=["color"],D8=y.forwardRef(function(t,a){var o=t.color,i=o===void 0?"currentColor":o,s=ao(t,M8);return y.createElement("svg",Object.assign({width:"15",height:"15",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},s,{ref:a}),y.createElement("path",{d:"M3.5 2C3.22386 2 3 2.22386 3 2.5V12.5C3 12.7761 3.22386 13 3.5 13H11.5C11.7761 13 12 12.7761 12 12.5V6H8.5C8.22386 6 8 5.77614 8 5.5V2H3.5ZM9 2.70711L11.2929 5H9V2.70711ZM2 2.5C2 1.67157 2.67157 1 3.5 1H8.5C8.63261 1 8.75979 1.05268 8.85355 1.14645L12.8536 5.14645C12.9473 5.24021 13 5.36739 13 5.5V12.5C13 13.3284 12.3284 14 11.5 14H3.5C2.67157 14 2 13.3284 2 12.5V2.5Z",fill:i,fillRule:"evenodd",clipRule:"evenodd"}))}),O8=["color"],N8=y.forwardRef(function(t,a){var o=t.color,i=o===void 0?"currentColor":o,s=ao(t,O8);return y.createElement("svg",Object.assign({width:"15",height:"15",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},s,{ref:a}),y.createElement("path",{d:"M1.5 5.25C1.91421 5.25 2.25 4.91421 2.25 4.5C2.25 4.08579 1.91421 3.75 1.5 3.75C1.08579 3.75 0.75 4.08579 0.75 4.5C0.75 4.91421 1.08579 5.25 1.5 5.25ZM4 4.5C4 4.22386 4.22386 4 4.5 4H13.5C13.7761 4 14 4.22386 14 4.5C14 4.77614 13.7761 5 13.5 5H4.5C4.22386 5 4 4.77614 4 4.5ZM4.5 7C4.22386 7 4 7.22386 4 7.5C4 7.77614 4.22386 8 4.5 8H13.5C13.7761 8 14 7.77614 14 7.5C14 7.22386 13.7761 7 13.5 7H4.5ZM4.5 10C4.22386 10 4 10.2239 4 10.5C4 10.7761 4.22386 11 4.5 11H13.5C13.7761 11 14 10.7761 14 10.5C14 10.2239 13.7761 10 13.5 10H4.5ZM2.25 7.5C2.25 7.91421 1.91421 8.25 1.5 8.25C1.08579 8.25 0.75 7.91421 0.75 7.5C0.75 7.08579 1.08579 6.75 1.5 6.75C1.91421 6.75 2.25 7.08579 2.25 7.5ZM1.5 11.25C1.91421 11.25 2.25 10.9142 2.25 10.5C2.25 10.0858 1.91421 9.75 1.5 9.75C1.08579 9.75 0.75 10.0858 0.75 10.5C0.75 10.9142 1.08579 11.25 1.5 11.25Z",fill:i,fillRule:"evenodd",clipRule:"evenodd"}))}),L8=["color"],vd=y.forwardRef(function(t,a){var o=t.color,i=o===void 0?"currentColor":o,s=ao(t,L8);return y.createElement("svg",Object.assign({width:"15",height:"15",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},s,{ref:a}),y.createElement("path",{d:"M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z",fill:i,fillRule:"evenodd",clipRule:"evenodd"}))}),j8=["color"],F8=y.forwardRef(function(t,a){var o=t.color,i=o===void 0?"currentColor":o,s=ao(t,j8);return y.createElement("svg",Object.assign({width:"15",height:"15",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg"},s,{ref:a}),y.createElement("path",{d:"M12.1464 1.14645C12.3417 0.951184 12.6583 0.951184 12.8535 1.14645L14.8535 3.14645C15.0488 3.34171 15.0488 3.65829 14.8535 3.85355L10.9109 7.79618C10.8349 7.87218 10.7471 7.93543 10.651 7.9835L6.72359 9.94721C6.53109 10.0435 6.29861 10.0057 6.14643 9.85355C5.99425 9.70137 5.95652 9.46889 6.05277 9.27639L8.01648 5.34897C8.06455 5.25283 8.1278 5.16507 8.2038 5.08907L12.1464 1.14645ZM12.5 2.20711L8.91091 5.79618L7.87266 7.87267L8.12731 8.12732L10.2038 7.08907L13.7929 3.5L12.5 2.20711ZM9.99998 2L8.99998 3H4.9C4.47171 3 4.18056 3.00039 3.95552 3.01877C3.73631 3.03668 3.62421 3.06915 3.54601 3.10899C3.35785 3.20487 3.20487 3.35785 3.10899 3.54601C3.06915 3.62421 3.03669 3.73631 3.01878 3.95552C3.00039 4.18056 3 4.47171 3 4.9V11.1C3 11.5283 3.00039 11.8194 3.01878 12.0445C3.03669 12.2637 3.06915 12.3758 3.10899 12.454C3.20487 12.6422 3.35785 12.7951 3.54601 12.891C3.62421 12.9309 3.73631 12.9633 3.95552 12.9812C4.18056 12.9996 4.47171 13 4.9 13H11.1C11.5283 13 11.8194 12.9996 12.0445 12.9812C12.2637 12.9633 12.3758 12.9309 12.454 12.891C12.6422 12.7951 12.7951 12.6422 12.891 12.454C12.9309 12.3758 12.9633 12.2637 12.9812 12.0445C12.9996 11.8194 13 11.5283 13 11.1V6.99998L14 5.99998V11.1V11.1207C14 11.5231 14 11.8553 13.9779 12.1259C13.9549 12.407 13.9057 12.6653 13.782 12.908C13.5903 13.2843 13.2843 13.5903 12.908 13.782C12.6653 13.9057 12.407 13.9549 12.1259 13.9779C11.8553 14 11.5231 14 11.1207 14H11.1H4.9H4.87934C4.47686 14 4.14468 14 3.87409 13.9779C3.59304 13.9549 3.33469 13.9057 3.09202 13.782C2.7157 13.5903 2.40973 13.2843 2.21799 12.908C2.09434 12.6653 2.04506 12.407 2.0221 12.1259C1.99999 11.8553 1.99999 11.5231 2 11.1207V11.1206V11.1V4.9V4.87935V4.87932V4.87931C1.99999 4.47685 1.99999 4.14468 2.0221 3.87409C2.04506 3.59304 2.09434 3.33469 2.21799 3.09202C2.40973 2.71569 2.7157 2.40973 3.09202 2.21799C3.33469 2.09434 3.59304 2.04506 3.87409 2.0221C4.14468 1.99999 4.47685 1.99999 4.87932 2H4.87935H4.9H9.99998Z",fill:i,fillRule:"evenodd",clipRule:"evenodd"}))});function Jr(t,a){if(typeof t!="object"||t===null)return t;if(Array.isArray(t))return t.map((i,s)=>Jr(i,s));const o=t.props.children?{...t.props,children:Jr(t.props.children)}:t.props;return gt.createElement(t.type,{...o,key:a})}function k8({hide:t}){const{banner:a}=Ot(),o=y.useMemo(()=>{const i=a?.content??"";if(!i)return null;if(typeof i!="string")return()=>Jr(i);const{default:s}=E8(i,{...G4,Fragment:y.Fragment});return s},[a]);return o?g.jsx("div",{className:me(v8),style:aa({[h8]:a?.backgroundColor,[m8]:a?.textColor}),children:g.jsxs("div",{className:me(y8),children:[g.jsx("div",{className:me(g8),children:g.jsx(o,{})}),a?.dismissable!=="false"&&g.jsx("button",{className:me(A8),onClick:t,type:"button",children:g.jsx(T8,{width:14,height:14})})]})}):null}var z8="vocs_Content";function Xy({children:t,className:a}){return g.jsx("article",{className:me(a,z8),children:t})}const U8=({children:t})=>t,P8=({children:t})=>t,gd=({children:t})=>t;function Zy({items:t,pathname:a}){const o=a.replace(/\.html$/,""),i=[];for(const u of t)if(u.link&&(typeof u.match=="function"?u.match(o):o.startsWith(u.match||u.link)))i.push({id:u.id,children:[]});else if(u.items){const c=Zy({items:u.items,pathname:a});c.length>0&&i.push({id:u.id,children:c})}if(i.length===0)return[];const s=i[i.length-1];return[s.id,...s.children]}function Rl({items:t,pathname:a}){return y.useMemo(()=>Zy({items:t,pathname:a}),[t,a])}function wr(){const t=y.useContext(Jy);if(!t)throw new Error("`usePageData` must be used within `PageDataContext.Provider`.");return t}const Jy=y.createContext(void 0);function $u(){const{pathname:t}=ft(),a=Ot(),{sidebar:o}=a,i=y.useMemo(()=>{if(!o)return;const s=Object.keys(o).filter(u=>t.startsWith(u));return s[s.length-1]},[o,t]);return o?Array.isArray(o)?{items:o}:i?Array.isArray(o[i])?{key:i,items:o[i]}:{...o[i],key:i}:{items:[]}:{items:[]}}function _r(){const{aiCta:t}=Ot(),a=$u(),{frontmatter:o}=wr(),{layout:i,showLogo:s,showAiCta:u,showOutline:c,showSidebar:d,showTopNav:v}=o||{},m=i??"docs";return{layout:m,get showLogo(){return typeof s<"u"?s:!0},get showAiCta(){return typeof u<"u"?u:t===!1?!1:m==="docs"},get showOutline(){return typeof c<"u"?c:m==="docs"},get showSidebar(){return a.items.length===0?!1:typeof d<"u"?d:!(m==="minimal"||m==="landing")},get showTopNav(){return typeof v<"u"?v:!0}}}function Re(t,a,{checkForDefaultPrevented:o=!0}={}){return function(s){if(t?.(s),o===!1||!s.defaultPrevented)return a?.(s)}}function Ig(t,a){if(typeof t=="function")return t(a);t!=null&&(t.current=a)}function di(...t){return a=>{let o=!1;const i=t.map(s=>{const u=Ig(s,a);return!o&&typeof u=="function"&&(o=!0),u});if(o)return()=>{for(let s=0;s<i.length;s++){const u=i[s];typeof u=="function"?u():Ig(t[s],null)}}}}function yt(...t){return y.useCallback(di(...t),t)}function I8(t,a){const o=y.createContext(a),i=u=>{const{children:c,...d}=u,v=y.useMemo(()=>d,Object.values(d));return g.jsx(o.Provider,{value:v,children:c})};i.displayName=t+"Provider";function s(u){const c=y.useContext(o);if(c)return c;if(a!==void 0)return a;throw new Error(`\`${u}\` must be used within \`${t}\``)}return[i,s]}function ra(t,a=[]){let o=[];function i(u,c){const d=y.createContext(c),v=o.length;o=[...o,c];const m=p=>{const{scope:C,children:b,...S}=p,x=C?.[t]?.[v]||d,w=y.useMemo(()=>S,Object.values(S));return g.jsx(x.Provider,{value:w,children:b})};m.displayName=u+"Provider";function A(p,C){const b=C?.[t]?.[v]||d,S=y.useContext(b);if(S)return S;if(c!==void 0)return c;throw new Error(`\`${p}\` must be used within \`${u}\``)}return[m,A]}const s=()=>{const u=o.map(c=>y.createContext(c));return function(d){const v=d?.[t]||u;return y.useMemo(()=>({[`__scope${t}`]:{...d,[t]:v}}),[d,v])}};return s.scopeName=t,[i,H8(s,...a)]}function H8(...t){const a=t[0];if(t.length===1)return a;const o=()=>{const i=t.map(s=>({useScope:s(),scopeName:s.scopeName}));return function(u){const c=i.reduce((d,{useScope:v,scopeName:m})=>{const p=v(u)[`__scope${m}`];return{...d,...p}},{});return y.useMemo(()=>({[`__scope${a.scopeName}`]:c}),[c])}};return o.scopeName=a.scopeName,o}var Gn=globalThis?.document?y.useLayoutEffect:()=>{},B8=li[" useId ".trim().toString()]||(()=>{}),$8=0;function $n(t){const[a,o]=y.useState(B8());return Gn(()=>{o(i=>i??String($8++))},[t]),t||(a?`radix-${a}`:"")}var V8=li[" useInsertionEffect ".trim().toString()]||Gn;function Ca({prop:t,defaultProp:a,onChange:o=()=>{},caller:i}){const[s,u,c]=q8({defaultProp:a,onChange:o}),d=t!==void 0,v=d?t:s;{const A=y.useRef(t!==void 0);y.useEffect(()=>{const p=A.current;p!==d&&console.warn(`${i} is changing from ${p?"controlled":"uncontrolled"} to ${d?"controlled":"uncontrolled"}. Components should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled value for the lifetime of the component.`),A.current=d},[d,i])}const m=y.useCallback(A=>{if(d){const p=G8(A)?A(t):A;p!==t&&c.current?.(p)}else u(A)},[d,t,u,c]);return[v,m]}function q8({defaultProp:t,onChange:a}){const[o,i]=y.useState(t),s=y.useRef(o),u=y.useRef(a);return V8(()=>{u.current=a},[a]),y.useEffect(()=>{s.current!==o&&(u.current?.(o),s.current=o)},[o,s]),[o,i,u]}function G8(t){return typeof t=="function"}var yd=ry();const Wy=El(yd);function ai(t){const a=Y8(t),o=y.forwardRef((i,s)=>{const{children:u,...c}=i,d=y.Children.toArray(u),v=d.find(K8);if(v){const m=v.props.children,A=d.map(p=>p===v?y.Children.count(m)>1?y.Children.only(null):y.isValidElement(m)?m.props.children:null:p);return g.jsx(a,{...c,ref:s,children:y.isValidElement(m)?y.cloneElement(m,void 0,A):null})}return g.jsx(a,{...c,ref:s,children:u})});return o.displayName=`${t}.Slot`,o}function Y8(t){const a=y.forwardRef((o,i)=>{const{children:s,...u}=o;if(y.isValidElement(s)){const c=Z8(s),d=X8(u,s.props);return s.type!==y.Fragment&&(d.ref=i?di(i,c):c),y.cloneElement(s,d)}return y.Children.count(s)>1?y.Children.only(null):null});return a.displayName=`${t}.SlotClone`,a}var Q8=Symbol("radix.slottable");function K8(t){return y.isValidElement(t)&&typeof t.type=="function"&&"__radixId"in t.type&&t.type.__radixId===Q8}function X8(t,a){const o={...a};for(const i in a){const s=t[i],u=a[i];/^on[A-Z]/.test(i)?s&&u?o[i]=(...d)=>{const v=u(...d);return s(...d),v}:s&&(o[i]=s):i==="style"?o[i]={...s,...u}:i==="className"&&(o[i]=[s,u].filter(Boolean).join(" "))}return{...t,...o}}function Z8(t){let a=Object.getOwnPropertyDescriptor(t.props,"ref")?.get,o=a&&"isReactWarning"in a&&a.isReactWarning;return o?t.ref:(a=Object.getOwnPropertyDescriptor(t,"ref")?.get,o=a&&"isReactWarning"in a&&a.isReactWarning,o?t.props.ref:t.props.ref||t.ref)}var J8=["a","button","div","form","h2","h3","img","input","label","li","nav","ol","p","select","span","svg","ul"],ke=J8.reduce((t,a)=>{const o=ai(`Primitive.${a}`),i=y.forwardRef((s,u)=>{const{asChild:c,...d}=s,v=c?o:a;return typeof window<"u"&&(window[Symbol.for("radix-ui")]=!0),g.jsx(v,{...d,ref:u})});return i.displayName=`Primitive.${a}`,{...t,[a]:i}},{});function _u(t,a){t&&yd.flushSync(()=>t.dispatchEvent(a))}function on(t){const a=y.useRef(t);return y.useEffect(()=>{a.current=t}),y.useMemo(()=>(...o)=>a.current?.(...o),[])}function W8(t,a=globalThis?.document){const o=on(t);y.useEffect(()=>{const i=s=>{s.key==="Escape"&&o(s)};return a.addEventListener("keydown",i,{capture:!0}),()=>a.removeEventListener("keydown",i,{capture:!0})},[o,a])}var eS="DismissableLayer",Tf="dismissableLayer.update",tS="dismissableLayer.pointerDownOutside",nS="dismissableLayer.focusOutside",Hg,eA=y.createContext({layers:new Set,layersWithOutsidePointerEventsDisabled:new Set,branches:new Set}),Tl=y.forwardRef((t,a)=>{const{disableOutsidePointerEvents:o=!1,onEscapeKeyDown:i,onPointerDownOutside:s,onFocusOutside:u,onInteractOutside:c,onDismiss:d,...v}=t,m=y.useContext(eA),[A,p]=y.useState(null),C=A?.ownerDocument??globalThis?.document,[,b]=y.useState({}),S=yt(a,F=>p(F)),x=Array.from(m.layers),[w]=[...m.layersWithOutsidePointerEventsDisabled].slice(-1),D=x.indexOf(w),T=A?x.indexOf(A):-1,R=m.layersWithOutsidePointerEventsDisabled.size>0,_=T>=D,N=oS(F=>{const O=F.target,I=[...m.branches].some(re=>re.contains(O));!_||I||(s?.(F),c?.(F),F.defaultPrevented||d?.())},C),j=iS(F=>{const O=F.target;[...m.branches].some(re=>re.contains(O))||(u?.(F),c?.(F),F.defaultPrevented||d?.())},C);return W8(F=>{T===m.layers.size-1&&(i?.(F),!F.defaultPrevented&&d&&(F.preventDefault(),d()))},C),y.useEffect(()=>{if(A)return o&&(m.layersWithOutsidePointerEventsDisabled.size===0&&(Hg=C.body.style.pointerEvents,C.body.style.pointerEvents="none"),m.layersWithOutsidePointerEventsDisabled.add(A)),m.layers.add(A),Bg(),()=>{o&&m.layersWithOutsidePointerEventsDisabled.size===1&&(C.body.style.pointerEvents=Hg)}},[A,C,o,m]),y.useEffect(()=>()=>{A&&(m.layers.delete(A),m.layersWithOutsidePointerEventsDisabled.delete(A),Bg())},[A,m]),y.useEffect(()=>{const F=()=>b({});return document.addEventListener(Tf,F),()=>document.removeEventListener(Tf,F)},[]),g.jsx(ke.div,{...v,ref:S,style:{pointerEvents:R?_?"auto":"none":void 0,...t.style},onFocusCapture:Re(t.onFocusCapture,j.onFocusCapture),onBlurCapture:Re(t.onBlurCapture,j.onBlurCapture),onPointerDownCapture:Re(t.onPointerDownCapture,N.onPointerDownCapture)})});Tl.displayName=eS;var aS="DismissableLayerBranch",rS=y.forwardRef((t,a)=>{const o=y.useContext(eA),i=y.useRef(null),s=yt(a,i);return y.useEffect(()=>{const u=i.current;if(u)return o.branches.add(u),()=>{o.branches.delete(u)}},[o.branches]),g.jsx(ke.div,{...t,ref:s})});rS.displayName=aS;function oS(t,a=globalThis?.document){const o=on(t),i=y.useRef(!1),s=y.useRef(()=>{});return y.useEffect(()=>{const u=d=>{if(d.target&&!i.current){let v=function(){tA(tS,o,m,{discrete:!0})};const m={originalEvent:d};d.pointerType==="touch"?(a.removeEventListener("click",s.current),s.current=v,a.addEventListener("click",s.current,{once:!0})):v()}else a.removeEventListener("click",s.current);i.current=!1},c=window.setTimeout(()=>{a.addEventListener("pointerdown",u)},0);return()=>{window.clearTimeout(c),a.removeEventListener("pointerdown",u),a.removeEventListener("click",s.current)}},[a,o]),{onPointerDownCapture:()=>i.current=!0}}function iS(t,a=globalThis?.document){const o=on(t),i=y.useRef(!1);return y.useEffect(()=>{const s=u=>{u.target&&!i.current&&tA(nS,o,{originalEvent:u},{discrete:!1})};return a.addEventListener("focusin",s),()=>a.removeEventListener("focusin",s)},[a,o]),{onFocusCapture:()=>i.current=!0,onBlurCapture:()=>i.current=!1}}function Bg(){const t=new CustomEvent(Tf);document.dispatchEvent(t)}function tA(t,a,o,{discrete:i}){const s=o.originalEvent.target,u=new CustomEvent(t,{bubbles:!1,cancelable:!0,detail:o});a&&s.addEventListener(t,a,{once:!0}),i?_u(s,u):s.dispatchEvent(u)}var j2="focusScope.autoFocusOnMount",F2="focusScope.autoFocusOnUnmount",$g={bubbles:!1,cancelable:!0},lS="FocusScope",Vu=y.forwardRef((t,a)=>{const{loop:o=!1,trapped:i=!1,onMountAutoFocus:s,onUnmountAutoFocus:u,...c}=t,[d,v]=y.useState(null),m=on(s),A=on(u),p=y.useRef(null),C=yt(a,x=>v(x)),b=y.useRef({paused:!1,pause(){this.paused=!0},resume(){this.paused=!1}}).current;y.useEffect(()=>{if(i){let x=function(R){if(b.paused||!d)return;const _=R.target;d.contains(_)?p.current=_:Ar(p.current,{select:!0})},w=function(R){if(b.paused||!d)return;const _=R.relatedTarget;_!==null&&(d.contains(_)||Ar(p.current,{select:!0}))},D=function(R){if(document.activeElement===document.body)for(const N of R)N.removedNodes.length>0&&Ar(d)};document.addEventListener("focusin",x),document.addEventListener("focusout",w);const T=new MutationObserver(D);return d&&T.observe(d,{childList:!0,subtree:!0}),()=>{document.removeEventListener("focusin",x),document.removeEventListener("focusout",w),T.disconnect()}}},[i,d,b.paused]),y.useEffect(()=>{if(d){qg.add(b);const x=document.activeElement;if(!d.contains(x)){const D=new CustomEvent(j2,$g);d.addEventListener(j2,m),d.dispatchEvent(D),D.defaultPrevented||(sS(hS(nA(d)),{select:!0}),document.activeElement===x&&Ar(d))}return()=>{d.removeEventListener(j2,m),setTimeout(()=>{const D=new CustomEvent(F2,$g);d.addEventListener(F2,A),d.dispatchEvent(D),D.defaultPrevented||Ar(x??document.body,{select:!0}),d.removeEventListener(F2,A),qg.remove(b)},0)}}},[d,m,A,b]);const S=y.useCallback(x=>{if(!o&&!i||b.paused)return;const w=x.key==="Tab"&&!x.altKey&&!x.ctrlKey&&!x.metaKey,D=document.activeElement;if(w&&D){const T=x.currentTarget,[R,_]=uS(T);R&&_?!x.shiftKey&&D===_?(x.preventDefault(),o&&Ar(R,{select:!0})):x.shiftKey&&D===R&&(x.preventDefault(),o&&Ar(_,{select:!0})):D===T&&x.preventDefault()}},[o,i,b.paused]);return g.jsx(ke.div,{tabIndex:-1,...c,ref:C,onKeyDown:S})});Vu.displayName=lS;function sS(t,{select:a=!1}={}){const o=document.activeElement;for(const i of t)if(Ar(i,{select:a}),document.activeElement!==o)return}function uS(t){const a=nA(t),o=Vg(a,t),i=Vg(a.reverse(),t);return[o,i]}function nA(t){const a=[],o=document.createTreeWalker(t,NodeFilter.SHOW_ELEMENT,{acceptNode:i=>{const s=i.tagName==="INPUT"&&i.type==="hidden";return i.disabled||i.hidden||s?NodeFilter.FILTER_SKIP:i.tabIndex>=0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}});for(;o.nextNode();)a.push(o.currentNode);return a}function Vg(t,a){for(const o of t)if(!cS(o,{upTo:a}))return o}function cS(t,{upTo:a}){if(getComputedStyle(t).visibility==="hidden")return!0;for(;t;){if(a!==void 0&&t===a)return!1;if(getComputedStyle(t).display==="none")return!0;t=t.parentElement}return!1}function fS(t){return t instanceof HTMLInputElement&&"select"in t}function Ar(t,{select:a=!1}={}){if(t&&t.focus){const o=document.activeElement;t.focus({preventScroll:!0}),t!==o&&fS(t)&&a&&t.select()}}var qg=dS();function dS(){let t=[];return{add(a){const o=t[0];a!==o&&o?.pause(),t=Gg(t,a),t.unshift(a)},remove(a){t=Gg(t,a),t[0]?.resume()}}}function Gg(t,a){const o=[...t],i=o.indexOf(a);return i!==-1&&o.splice(i,1),o}function hS(t){return t.filter(a=>a.tagName!=="A")}var pS="Portal",qu=y.forwardRef((t,a)=>{const{container:o,...i}=t,[s,u]=y.useState(!1);Gn(()=>u(!0),[]);const c=o||s&&globalThis?.document?.body;return c?Wy.createPortal(g.jsx(ke.div,{...i,ref:a}),c):null});qu.displayName=pS;function mS(t,a){return y.useReducer((o,i)=>a[o][i]??o,t)}var ln=t=>{const{present:a,children:o}=t,i=vS(a),s=typeof o=="function"?o({present:i.isPresent}):y.Children.only(o),u=yt(i.ref,gS(s));return typeof o=="function"||i.isPresent?y.cloneElement(s,{ref:u}):null};ln.displayName="Presence";function vS(t){const[a,o]=y.useState(),i=y.useRef(null),s=y.useRef(t),u=y.useRef("none"),c=t?"mounted":"unmounted",[d,v]=mS(c,{mounted:{UNMOUNT:"unmounted",ANIMATION_OUT:"unmountSuspended"},unmountSuspended:{MOUNT:"mounted",ANIMATION_END:"unmounted"},unmounted:{MOUNT:"mounted"}});return y.useEffect(()=>{const m=au(i.current);u.current=d==="mounted"?m:"none"},[d]),Gn(()=>{const m=i.current,A=s.current;if(A!==t){const C=u.current,b=au(m);t?v("MOUNT"):b==="none"||m?.display==="none"?v("UNMOUNT"):v(A&&C!==b?"ANIMATION_OUT":"UNMOUNT"),s.current=t}},[t,v]),Gn(()=>{if(a){let m;const A=a.ownerDocument.defaultView??window,p=b=>{const x=au(i.current).includes(CSS.escape(b.animationName));if(b.target===a&&x&&(v("ANIMATION_END"),!s.current)){const w=a.style.animationFillMode;a.style.animationFillMode="forwards",m=A.setTimeout(()=>{a.style.animationFillMode==="forwards"&&(a.style.animationFillMode=w)})}},C=b=>{b.target===a&&(u.current=au(i.current))};return a.addEventListener("animationstart",C),a.addEventListener("animationcancel",p),a.addEventListener("animationend",p),()=>{A.clearTimeout(m),a.removeEventListener("animationstart",C),a.removeEventListener("animationcancel",p),a.removeEventListener("animationend",p)}}else v("ANIMATION_END")},[a,v]),{isPresent:["mounted","unmountSuspended"].includes(d),ref:y.useCallback(m=>{i.current=m?getComputedStyle(m):null,o(m)},[])}}function au(t){return t?.animationName||"none"}function gS(t){let a=Object.getOwnPropertyDescriptor(t.props,"ref")?.get,o=a&&"isReactWarning"in a&&a.isReactWarning;return o?t.ref:(a=Object.getOwnPropertyDescriptor(t,"ref")?.get,o=a&&"isReactWarning"in a&&a.isReactWarning,o?t.props.ref:t.props.ref||t.ref)}var k2=0;function Ad(){y.useEffect(()=>{const t=document.querySelectorAll("[data-radix-focus-guard]");return document.body.insertAdjacentElement("afterbegin",t[0]??Yg()),document.body.insertAdjacentElement("beforeend",t[1]??Yg()),k2++,()=>{k2===1&&document.querySelectorAll("[data-radix-focus-guard]").forEach(a=>a.remove()),k2--}},[])}function Yg(){const t=document.createElement("span");return t.setAttribute("data-radix-focus-guard",""),t.tabIndex=0,t.style.outline="none",t.style.opacity="0",t.style.position="fixed",t.style.pointerEvents="none",t}var ma=function(){return ma=Object.assign||function(a){for(var o,i=1,s=arguments.length;i<s;i++){o=arguments[i];for(var u in o)Object.prototype.hasOwnProperty.call(o,u)&&(a[u]=o[u])}return a},ma.apply(this,arguments)};function aA(t,a){var o={};for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&a.indexOf(i)<0&&(o[i]=t[i]);if(t!=null&&typeof Object.getOwnPropertySymbols=="function")for(var s=0,i=Object.getOwnPropertySymbols(t);s<i.length;s++)a.indexOf(i[s])<0&&Object.prototype.propertyIsEnumerable.call(t,i[s])&&(o[i[s]]=t[i[s]]);return o}function yS(t,a,o){if(o||arguments.length===2)for(var i=0,s=a.length,u;i<s;i++)(u||!(i in a))&&(u||(u=Array.prototype.slice.call(a,0,i)),u[i]=a[i]);return t.concat(u||Array.prototype.slice.call(a))}var Cu="right-scroll-bar-position",bu="width-before-scroll-bar",AS="with-scroll-bars-hidden",CS="--removed-body-scroll-bar-size";function z2(t,a){return typeof t=="function"?t(a):t&&(t.current=a),t}function bS(t,a){var o=y.useState(function(){return{value:t,callback:a,facade:{get current(){return o.value},set current(i){var s=o.value;s!==i&&(o.value=i,o.callback(i,s))}}}})[0];return o.callback=a,o.facade}var ES=typeof window<"u"?y.useLayoutEffect:y.useEffect,Qg=new WeakMap;function SS(t,a){var o=bS(null,function(i){return t.forEach(function(s){return z2(s,i)})});return ES(function(){var i=Qg.get(o);if(i){var s=new Set(i),u=new Set(t),c=o.current;s.forEach(function(d){u.has(d)||z2(d,null)}),u.forEach(function(d){s.has(d)||z2(d,c)})}Qg.set(o,t)},[t]),o}function xS(t){return t}function wS(t,a){a===void 0&&(a=xS);var o=[],i=!1,s={read:function(){if(i)throw new Error("Sidecar: could not `read` from an `assigned` medium. `read` could be used only with `useMedium`.");return o.length?o[o.length-1]:t},useMedium:function(u){var c=a(u,i);return o.push(c),function(){o=o.filter(function(d){return d!==c})}},assignSyncMedium:function(u){for(i=!0;o.length;){var c=o;o=[],c.forEach(u)}o={push:function(d){return u(d)},filter:function(){return o}}},assignMedium:function(u){i=!0;var c=[];if(o.length){var d=o;o=[],d.forEach(u),c=o}var v=function(){var A=c;c=[],A.forEach(u)},m=function(){return Promise.resolve().then(v)};m(),o={push:function(A){c.push(A),m()},filter:function(A){return c=c.filter(A),o}}}};return s}function _S(t){t===void 0&&(t={});var a=wS(null);return a.options=ma({async:!0,ssr:!1},t),a}var rA=function(t){var a=t.sideCar,o=aA(t,["sideCar"]);if(!a)throw new Error("Sidecar: please provide `sideCar` property to import the right car");var i=a.read();if(!i)throw new Error("Sidecar medium not found");return y.createElement(i,ma({},o))};rA.isSideCarExport=!0;function RS(t,a){return t.useMedium(a),rA}var oA=_S(),U2=function(){},Gu=y.forwardRef(function(t,a){var o=y.useRef(null),i=y.useState({onScrollCapture:U2,onWheelCapture:U2,onTouchMoveCapture:U2}),s=i[0],u=i[1],c=t.forwardProps,d=t.children,v=t.className,m=t.removeScrollBar,A=t.enabled,p=t.shards,C=t.sideCar,b=t.noRelative,S=t.noIsolation,x=t.inert,w=t.allowPinchZoom,D=t.as,T=D===void 0?"div":D,R=t.gapMode,_=aA(t,["forwardProps","children","className","removeScrollBar","enabled","shards","sideCar","noRelative","noIsolation","inert","allowPinchZoom","as","gapMode"]),N=C,j=SS([o,a]),F=ma(ma({},_),s);return y.createElement(y.Fragment,null,A&&y.createElement(N,{sideCar:oA,removeScrollBar:m,shards:p,noRelative:b,noIsolation:S,inert:x,setCallbacks:u,allowPinchZoom:!!w,lockRef:o,gapMode:R}),c?y.cloneElement(y.Children.only(d),ma(ma({},F),{ref:j})):y.createElement(T,ma({},F,{className:v,ref:j}),d))});Gu.defaultProps={enabled:!0,removeScrollBar:!0,inert:!1};Gu.classNames={fullWidth:bu,zeroRight:Cu};var TS=function(){if(typeof __webpack_nonce__<"u")return __webpack_nonce__};function MS(){if(!document)return null;var t=document.createElement("style");t.type="text/css";var a=TS();return a&&t.setAttribute("nonce",a),t}function DS(t,a){t.styleSheet?t.styleSheet.cssText=a:t.appendChild(document.createTextNode(a))}function OS(t){var a=document.head||document.getElementsByTagName("head")[0];a.appendChild(t)}var NS=function(){var t=0,a=null;return{add:function(o){t==0&&(a=MS())&&(DS(a,o),OS(a)),t++},remove:function(){t--,!t&&a&&(a.parentNode&&a.parentNode.removeChild(a),a=null)}}},LS=function(){var t=NS();return function(a,o){y.useEffect(function(){return t.add(a),function(){t.remove()}},[a&&o])}},iA=function(){var t=LS(),a=function(o){var i=o.styles,s=o.dynamic;return t(i,s),null};return a},jS={left:0,top:0,right:0,gap:0},P2=function(t){return parseInt(t||"",10)||0},FS=function(t){var a=window.getComputedStyle(document.body),o=a[t==="padding"?"paddingLeft":"marginLeft"],i=a[t==="padding"?"paddingTop":"marginTop"],s=a[t==="padding"?"paddingRight":"marginRight"];return[P2(o),P2(i),P2(s)]},kS=function(t){if(t===void 0&&(t="margin"),typeof window>"u")return jS;var a=FS(t),o=document.documentElement.clientWidth,i=window.innerWidth;return{left:a[0],top:a[1],right:a[2],gap:Math.max(0,i-o+a[2]-a[0])}},zS=iA(),Wo="data-scroll-locked",US=function(t,a,o,i){var s=t.left,u=t.top,c=t.right,d=t.gap;return o===void 0&&(o="margin"),` |
|
| 14 | + | .`.concat(AS,` { |
|
| 15 | + | overflow: hidden `).concat(i,`; |
|
| 16 | + | padding-right: `).concat(d,"px ").concat(i,`; |
|
| 17 | + | } |
|
| 18 | + | body[`).concat(Wo,`] { |
|
| 19 | + | overflow: hidden `).concat(i,`; |
|
| 20 | + | overscroll-behavior: contain; |
|
| 21 | + | `).concat([a&&"position: relative ".concat(i,";"),o==="margin"&&` |
|
| 22 | + | padding-left: `.concat(s,`px; |
|
| 23 | + | padding-top: `).concat(u,`px; |
|
| 24 | + | padding-right: `).concat(c,`px; |
|
| 25 | + | margin-left:0; |
|
| 26 | + | margin-top:0; |
|
| 27 | + | margin-right: `).concat(d,"px ").concat(i,`; |
|
| 28 | + | `),o==="padding"&&"padding-right: ".concat(d,"px ").concat(i,";")].filter(Boolean).join(""),` |
|
| 29 | + | } |
|
| 30 | + | ||
| 31 | + | .`).concat(Cu,` { |
|
| 32 | + | right: `).concat(d,"px ").concat(i,`; |
|
| 33 | + | } |
|
| 34 | + | ||
| 35 | + | .`).concat(bu,` { |
|
| 36 | + | margin-right: `).concat(d,"px ").concat(i,`; |
|
| 37 | + | } |
|
| 38 | + | ||
| 39 | + | .`).concat(Cu," .").concat(Cu,` { |
|
| 40 | + | right: 0 `).concat(i,`; |
|
| 41 | + | } |
|
| 42 | + | ||
| 43 | + | .`).concat(bu," .").concat(bu,` { |
|
| 44 | + | margin-right: 0 `).concat(i,`; |
|
| 45 | + | } |
|
| 46 | + | ||
| 47 | + | body[`).concat(Wo,`] { |
|
| 48 | + | `).concat(CS,": ").concat(d,`px; |
|
| 49 | + | } |
|
| 50 | + | `)},Kg=function(){var t=parseInt(document.body.getAttribute(Wo)||"0",10);return isFinite(t)?t:0},PS=function(){y.useEffect(function(){return document.body.setAttribute(Wo,(Kg()+1).toString()),function(){var t=Kg()-1;t<=0?document.body.removeAttribute(Wo):document.body.setAttribute(Wo,t.toString())}},[])},IS=function(t){var a=t.noRelative,o=t.noImportant,i=t.gapMode,s=i===void 0?"margin":i;PS();var u=y.useMemo(function(){return kS(s)},[s]);return y.createElement(zS,{styles:US(u,!a,s,o?"":"!important")})},Mf=!1;if(typeof window<"u")try{var ru=Object.defineProperty({},"passive",{get:function(){return Mf=!0,!0}});window.addEventListener("test",ru,ru),window.removeEventListener("test",ru,ru)}catch{Mf=!1}var qo=Mf?{passive:!1}:!1,HS=function(t){return t.tagName==="TEXTAREA"},lA=function(t,a){if(!(t instanceof Element))return!1;var o=window.getComputedStyle(t);return o[a]!=="hidden"&&!(o.overflowY===o.overflowX&&!HS(t)&&o[a]==="visible")},BS=function(t){return lA(t,"overflowY")},$S=function(t){return lA(t,"overflowX")},Xg=function(t,a){var o=a.ownerDocument,i=a;do{typeof ShadowRoot<"u"&&i instanceof ShadowRoot&&(i=i.host);var s=sA(t,i);if(s){var u=uA(t,i),c=u[1],d=u[2];if(c>d)return!0}i=i.parentNode}while(i&&i!==o.body);return!1},VS=function(t){var a=t.scrollTop,o=t.scrollHeight,i=t.clientHeight;return[a,o,i]},qS=function(t){var a=t.scrollLeft,o=t.scrollWidth,i=t.clientWidth;return[a,o,i]},sA=function(t,a){return t==="v"?BS(a):$S(a)},uA=function(t,a){return t==="v"?VS(a):qS(a)},GS=function(t,a){return t==="h"&&a==="rtl"?-1:1},YS=function(t,a,o,i,s){var u=GS(t,window.getComputedStyle(a).direction),c=u*i,d=o.target,v=a.contains(d),m=!1,A=c>0,p=0,C=0;do{if(!d)break;var b=uA(t,d),S=b[0],x=b[1],w=b[2],D=x-w-u*S;(S||D)&&sA(t,d)&&(p+=D,C+=S);var T=d.parentNode;d=T&&T.nodeType===Node.DOCUMENT_FRAGMENT_NODE?T.host:T}while(!v&&d!==document.body||v&&(a.contains(d)||a===d));return(A&&Math.abs(p)<1||!A&&Math.abs(C)<1)&&(m=!0),m},ou=function(t){return"changedTouches"in t?[t.changedTouches[0].clientX,t.changedTouches[0].clientY]:[0,0]},Zg=function(t){return[t.deltaX,t.deltaY]},Jg=function(t){return t&&"current"in t?t.current:t},QS=function(t,a){return t[0]===a[0]&&t[1]===a[1]},KS=function(t){return` |
|
| 51 | + | .block-interactivity-`.concat(t,` {pointer-events: none;} |
|
| 52 | + | .allow-interactivity-`).concat(t,` {pointer-events: all;} |
|
| 53 | + | `)},XS=0,Go=[];function ZS(t){var a=y.useRef([]),o=y.useRef([0,0]),i=y.useRef(),s=y.useState(XS++)[0],u=y.useState(iA)[0],c=y.useRef(t);y.useEffect(function(){c.current=t},[t]),y.useEffect(function(){if(t.inert){document.body.classList.add("block-interactivity-".concat(s));var x=yS([t.lockRef.current],(t.shards||[]).map(Jg),!0).filter(Boolean);return x.forEach(function(w){return w.classList.add("allow-interactivity-".concat(s))}),function(){document.body.classList.remove("block-interactivity-".concat(s)),x.forEach(function(w){return w.classList.remove("allow-interactivity-".concat(s))})}}},[t.inert,t.lockRef.current,t.shards]);var d=y.useCallback(function(x,w){if("touches"in x&&x.touches.length===2||x.type==="wheel"&&x.ctrlKey)return!c.current.allowPinchZoom;var D=ou(x),T=o.current,R="deltaX"in x?x.deltaX:T[0]-D[0],_="deltaY"in x?x.deltaY:T[1]-D[1],N,j=x.target,F=Math.abs(R)>Math.abs(_)?"h":"v";if("touches"in x&&F==="h"&&j.type==="range")return!1;var O=window.getSelection(),I=O&&O.anchorNode,re=I?I===j||I.contains(j):!1;if(re)return!1;var pe=Xg(F,j);if(!pe)return!0;if(pe?N=F:(N=F==="v"?"h":"v",pe=Xg(F,j)),!pe)return!1;if(!i.current&&"changedTouches"in x&&(R||_)&&(i.current=N),!N)return!0;var ce=i.current||N;return YS(ce,w,x,ce==="h"?R:_)},[]),v=y.useCallback(function(x){var w=x;if(!(!Go.length||Go[Go.length-1]!==u)){var D="deltaY"in w?Zg(w):ou(w),T=a.current.filter(function(N){return N.name===w.type&&(N.target===w.target||w.target===N.shadowParent)&&QS(N.delta,D)})[0];if(T&&T.should){w.cancelable&&w.preventDefault();return}if(!T){var R=(c.current.shards||[]).map(Jg).filter(Boolean).filter(function(N){return N.contains(w.target)}),_=R.length>0?d(w,R[0]):!c.current.noIsolation;_&&w.cancelable&&w.preventDefault()}}},[]),m=y.useCallback(function(x,w,D,T){var R={name:x,delta:w,target:D,should:T,shadowParent:JS(D)};a.current.push(R),setTimeout(function(){a.current=a.current.filter(function(_){return _!==R})},1)},[]),A=y.useCallback(function(x){o.current=ou(x),i.current=void 0},[]),p=y.useCallback(function(x){m(x.type,Zg(x),x.target,d(x,t.lockRef.current))},[]),C=y.useCallback(function(x){m(x.type,ou(x),x.target,d(x,t.lockRef.current))},[]);y.useEffect(function(){return Go.push(u),t.setCallbacks({onScrollCapture:p,onWheelCapture:p,onTouchMoveCapture:C}),document.addEventListener("wheel",v,qo),document.addEventListener("touchmove",v,qo),document.addEventListener("touchstart",A,qo),function(){Go=Go.filter(function(x){return x!==u}),document.removeEventListener("wheel",v,qo),document.removeEventListener("touchmove",v,qo),document.removeEventListener("touchstart",A,qo)}},[]);var b=t.removeScrollBar,S=t.inert;return y.createElement(y.Fragment,null,S?y.createElement(u,{styles:KS(s)}):null,b?y.createElement(IS,{noRelative:t.noRelative,gapMode:t.gapMode}):null)}function JS(t){for(var a=null;t!==null;)t instanceof ShadowRoot&&(a=t.host,t=t.host),t=t.parentNode;return a}const WS=RS(oA,ZS);var Yu=y.forwardRef(function(t,a){return y.createElement(Gu,ma({},t,{ref:a,sideCar:WS}))});Yu.classNames=Gu.classNames;var ex=function(t){if(typeof document>"u")return null;var a=Array.isArray(t)?t[0]:t;return a.ownerDocument.body},Yo=new WeakMap,iu=new WeakMap,lu={},I2=0,cA=function(t){return t&&(t.host||cA(t.parentNode))},tx=function(t,a){return a.map(function(o){if(t.contains(o))return o;var i=cA(o);return i&&t.contains(i)?i:(console.error("aria-hidden",o,"in not contained inside",t,". Doing nothing"),null)}).filter(function(o){return!!o})},nx=function(t,a,o,i){var s=tx(a,Array.isArray(t)?t:[t]);lu[o]||(lu[o]=new WeakMap);var u=lu[o],c=[],d=new Set,v=new Set(s),m=function(p){!p||d.has(p)||(d.add(p),m(p.parentNode))};s.forEach(m);var A=function(p){!p||v.has(p)||Array.prototype.forEach.call(p.children,function(C){if(d.has(C))A(C);else try{var b=C.getAttribute(i),S=b!==null&&b!=="false",x=(Yo.get(C)||0)+1,w=(u.get(C)||0)+1;Yo.set(C,x),u.set(C,w),c.push(C),x===1&&S&&iu.set(C,!0),w===1&&C.setAttribute(o,"true"),S||C.setAttribute(i,"true")}catch(D){console.error("aria-hidden: cannot operate on ",C,D)}})};return A(a),d.clear(),I2++,function(){c.forEach(function(p){var C=Yo.get(p)-1,b=u.get(p)-1;Yo.set(p,C),u.set(p,b),C||(iu.has(p)||p.removeAttribute(i),iu.delete(p)),b||p.removeAttribute(o)}),I2--,I2||(Yo=new WeakMap,Yo=new WeakMap,iu=new WeakMap,lu={})}},Cd=function(t,a,o){o===void 0&&(o="data-aria-hidden");var i=Array.from(Array.isArray(t)?t:[t]),s=ex(t);return s?(i.push.apply(i,Array.from(s.querySelectorAll("[aria-live], script"))),nx(i,s,o,"aria-hidden")):function(){return null}},Qu="Dialog",[fA]=ra(Qu),[ax,oa]=fA(Qu),dA=t=>{const{__scopeDialog:a,children:o,open:i,defaultOpen:s,onOpenChange:u,modal:c=!0}=t,d=y.useRef(null),v=y.useRef(null),[m,A]=Ca({prop:i,defaultProp:s??!1,onChange:u,caller:Qu});return g.jsx(ax,{scope:a,triggerRef:d,contentRef:v,contentId:$n(),titleId:$n(),descriptionId:$n(),open:m,onOpenChange:A,onOpenToggle:y.useCallback(()=>A(p=>!p),[A]),modal:c,children:o})};dA.displayName=Qu;var hA="DialogTrigger",pA=y.forwardRef((t,a)=>{const{__scopeDialog:o,...i}=t,s=oa(hA,o),u=yt(a,s.triggerRef);return g.jsx(ke.button,{type:"button","aria-haspopup":"dialog","aria-expanded":s.open,"aria-controls":s.contentId,"data-state":Sd(s.open),...i,ref:u,onClick:Re(t.onClick,s.onOpenToggle)})});pA.displayName=hA;var bd="DialogPortal",[rx,mA]=fA(bd,{forceMount:void 0}),vA=t=>{const{__scopeDialog:a,forceMount:o,children:i,container:s}=t,u=oa(bd,a);return g.jsx(rx,{scope:a,forceMount:o,children:y.Children.map(i,c=>g.jsx(ln,{present:o||u.open,children:g.jsx(qu,{asChild:!0,container:s,children:c})}))})};vA.displayName=bd;var Ru="DialogOverlay",gA=y.forwardRef((t,a)=>{const o=mA(Ru,t.__scopeDialog),{forceMount:i=o.forceMount,...s}=t,u=oa(Ru,t.__scopeDialog);return u.modal?g.jsx(ln,{present:i||u.open,children:g.jsx(ix,{...s,ref:a})}):null});gA.displayName=Ru;var ox=ai("DialogOverlay.RemoveScroll"),ix=y.forwardRef((t,a)=>{const{__scopeDialog:o,...i}=t,s=oa(Ru,o);return g.jsx(Yu,{as:ox,allowPinchZoom:!0,shards:[s.contentRef],children:g.jsx(ke.div,{"data-state":Sd(s.open),...i,ref:a,style:{pointerEvents:"auto",...i.style}})})}),Wr="DialogContent",yA=y.forwardRef((t,a)=>{const o=mA(Wr,t.__scopeDialog),{forceMount:i=o.forceMount,...s}=t,u=oa(Wr,t.__scopeDialog);return g.jsx(ln,{present:i||u.open,children:u.modal?g.jsx(lx,{...s,ref:a}):g.jsx(sx,{...s,ref:a})})});yA.displayName=Wr;var lx=y.forwardRef((t,a)=>{const o=oa(Wr,t.__scopeDialog),i=y.useRef(null),s=yt(a,o.contentRef,i);return y.useEffect(()=>{const u=i.current;if(u)return Cd(u)},[]),g.jsx(AA,{...t,ref:s,trapFocus:o.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:Re(t.onCloseAutoFocus,u=>{u.preventDefault(),o.triggerRef.current?.focus()}),onPointerDownOutside:Re(t.onPointerDownOutside,u=>{const c=u.detail.originalEvent,d=c.button===0&&c.ctrlKey===!0;(c.button===2||d)&&u.preventDefault()}),onFocusOutside:Re(t.onFocusOutside,u=>u.preventDefault())})}),sx=y.forwardRef((t,a)=>{const o=oa(Wr,t.__scopeDialog),i=y.useRef(!1),s=y.useRef(!1);return g.jsx(AA,{...t,ref:a,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:u=>{t.onCloseAutoFocus?.(u),u.defaultPrevented||(i.current||o.triggerRef.current?.focus(),u.preventDefault()),i.current=!1,s.current=!1},onInteractOutside:u=>{t.onInteractOutside?.(u),u.defaultPrevented||(i.current=!0,u.detail.originalEvent.type==="pointerdown"&&(s.current=!0));const c=u.target;o.triggerRef.current?.contains(c)&&u.preventDefault(),u.detail.originalEvent.type==="focusin"&&s.current&&u.preventDefault()}})}),AA=y.forwardRef((t,a)=>{const{__scopeDialog:o,trapFocus:i,onOpenAutoFocus:s,onCloseAutoFocus:u,...c}=t,d=oa(Wr,o),v=y.useRef(null),m=yt(a,v);return Ad(),g.jsxs(g.Fragment,{children:[g.jsx(Vu,{asChild:!0,loop:!0,trapped:i,onMountAutoFocus:s,onUnmountAutoFocus:u,children:g.jsx(Tl,{role:"dialog",id:d.contentId,"aria-describedby":d.descriptionId,"aria-labelledby":d.titleId,"data-state":Sd(d.open),...c,ref:m,onDismiss:()=>d.onOpenChange(!1)})}),g.jsxs(g.Fragment,{children:[g.jsx(fx,{titleId:d.titleId}),g.jsx(hx,{contentRef:v,descriptionId:d.descriptionId})]})]})}),Ed="DialogTitle",CA=y.forwardRef((t,a)=>{const{__scopeDialog:o,...i}=t,s=oa(Ed,o);return g.jsx(ke.h2,{id:s.titleId,...i,ref:a})});CA.displayName=Ed;var bA="DialogDescription",ux=y.forwardRef((t,a)=>{const{__scopeDialog:o,...i}=t,s=oa(bA,o);return g.jsx(ke.p,{id:s.descriptionId,...i,ref:a})});ux.displayName=bA;var EA="DialogClose",cx=y.forwardRef((t,a)=>{const{__scopeDialog:o,...i}=t,s=oa(EA,o);return g.jsx(ke.button,{type:"button",...i,ref:a,onClick:Re(t.onClick,()=>s.onOpenChange(!1))})});cx.displayName=EA;function Sd(t){return t?"open":"closed"}var SA="DialogTitleWarning",[xL,xA]=I8(SA,{contentName:Wr,titleName:Ed,docsSlug:"dialog"}),fx=({titleId:t})=>{const a=xA(SA),o=`\`${a.contentName}\` requires a \`${a.titleName}\` for the component to be accessible for screen reader users. |
|
| 54 | + | ||
| 55 | + | If you want to hide the \`${a.titleName}\`, you can wrap it with our VisuallyHidden component. |
|
| 56 | + | ||
| 57 | + | For more information, see https://radix-ui.com/primitives/docs/components/${a.docsSlug}`;return y.useEffect(()=>{t&&(document.getElementById(t)||console.error(o))},[o,t]),null},dx="DialogDescriptionWarning",hx=({contentRef:t,descriptionId:a})=>{const i=`Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${xA(dx).contentName}}.`;return y.useEffect(()=>{const s=t.current?.getAttribute("aria-describedby");a&&s&&(document.getElementById(a)||console.warn(i))},[i,t,a]),null},wA=dA,_A=pA,px=vA,mx=gA,vx=yA,gx=CA;function RA(t,a,o){try{return t(a)}catch(i){return K4("[nuqs] Error while parsing value `%s`: %O"+(o?" (for key `%s`)":""),a,i,o),null}}function qa(t){function a(o){if(typeof o>"u")return null;let i="";if(Array.isArray(o)){if(o[0]===void 0)return null;i=o[0]}return typeof o=="string"&&(i=o),RA(t.parse,i)}return{type:"single",eq:(o,i)=>o===i,...t,parseServerSide:a,withDefault(o){return{...this,defaultValue:o,parseServerSide(i){return a(i)??o}}},withOptions(o){return{...this,...o}}}}qa({parse:t=>t,serialize:String});qa({parse:t=>{const a=parseInt(t);return a==a?a:null},serialize:t=>""+Math.round(t)});qa({parse:t=>{const a=parseInt(t);return a==a?a-1:null},serialize:t=>""+Math.round(t+1)});qa({parse:t=>{const a=parseInt(t,16);return a==a?a:null},serialize:t=>{const a=Math.round(t).toString(16);return(a.length&1?"0":"")+a}});qa({parse:t=>{const a=parseFloat(t);return a==a?a:null},serialize:String});qa({parse:t=>t.toLowerCase()==="true",serialize:String});function xd(t,a){return t.valueOf()===a.valueOf()}qa({parse:t=>{const a=parseInt(t);return a==a?new Date(a):null},serialize:t=>""+t.valueOf(),eq:xd});qa({parse:t=>{const a=new Date(t);return a.valueOf()==a.valueOf()?a:null},serialize:t=>t.toISOString(),eq:xd});qa({parse:t=>{const a=new Date(t.slice(0,10));return a.valueOf()==a.valueOf()?a:null},serialize:t=>t.toISOString().slice(0,10),eq:xd});const H2=Wf(),yx={};function Ax(t,a={}){const o=y.useId(),i=ab(),s=rb(),{history:u="replace",scroll:c=i?.scroll??!1,shallow:d=i?.shallow??!0,throttleMs:v=hl.timeMs,limitUrlUpdates:m=i?.limitUrlUpdates,clearOnDefault:A=i?.clearOnDefault??!0,startTransition:p,urlKeys:C=yx}=a,b=Object.keys(t).join(","),S=y.useMemo(()=>Object.fromEntries(Object.keys(t).map(O=>[O,C[O]??O])),[b,JSON.stringify(C)]),x=nb(Object.values(S)),w=x.searchParams,D=y.useRef({}),T=y.useMemo(()=>Object.fromEntries(Object.keys(t).map(O=>[O,t[O].defaultValue??null])),[Object.values(t).map(({defaultValue:O})=>O).join(",")]),R=E2.useQueuedQueries(Object.values(S)),[_,N]=y.useState(()=>B2(t,C,w??new URLSearchParams,R).state),j=y.useRef(_);if(_t("[nuq+ %s `%s`] render - state: %O, iSP: %s",o,b,_,w),Object.keys(D.current).join("&")!==Object.values(S).join("&")){const{state:O,hasChanged:I}=B2(t,C,w,R,D.current,j.current);I&&(_t("[nuq+ %s `%s`] State changed: %O",o,b,{state:O,initialSearchParams:w,queuedQueries:R,queryRef:D.current,stateRef:j.current}),j.current=O,N(O)),D.current=Object.fromEntries(Object.entries(S).map(([re,pe])=>[pe,t[re]?.type==="multi"?w?.getAll(pe):w?.get(pe)??null]))}y.useEffect(()=>{const{state:O,hasChanged:I}=B2(t,C,w,R,D.current,j.current);I&&(_t("[nuq+ %s `%s`] State changed: %O",o,b,{state:O,initialSearchParams:w,queuedQueries:R,queryRef:D.current,stateRef:j.current}),j.current=O,N(O))},[Object.values(S).map(O=>`${O}=${w?.getAll(O)}`).join("&"),JSON.stringify(R)]),y.useEffect(()=>{const O=Object.keys(t).reduce((I,re)=>(I[re]=({state:pe,query:ce})=>{N(de=>{const{defaultValue:J}=t[re],fe=S[re],U=pe??J??null,H=de[re]??J??null;return Object.is(H,U)?(_t("[nuq+ %s `%s`] Cross-hook key sync %s: %O (default: %O). no change, skipping, resolved: %O",o,b,fe,pe,J,j.current),de):(j.current={...j.current,[re]:U},D.current[fe]=ce,_t("[nuq+ %s `%s`] Cross-hook key sync %s: %O (default: %O). updateInternalState, resolved: %O",o,b,fe,pe,J,j.current),j.current)})},I),{});for(const I of Object.keys(t)){const re=S[I];_t("[nuq+ %s `%s`] Subscribing to sync for `%s`",o,re,b),H2.on(re,O[I])}return()=>{for(const I of Object.keys(t)){const re=S[I];_t("[nuq+ %s `%s`] Unsubscribing to sync for `%s`",o,re,b),H2.off(re,O[I])}}},[b,S]);const F=y.useCallback((O,I={})=>{const re=Object.fromEntries(Object.keys(t).map(H=>[H,null])),pe=typeof O=="function"?O(Wg(j.current,T))??re:O??re;_t("[nuq+ %s `%s`] setState: %O",o,b,pe);let ce,de=0,J=!1;const fe=[];for(let[H,K]of Object.entries(pe)){const G=t[H],se=S[H];if(!G||K===void 0)continue;(I.clearOnDefault??G.clearOnDefault??A)&&K!==null&&G.defaultValue!==void 0&&(G.eq??((ne,ie)=>ne===ie))(K,G.defaultValue)&&(K=null);const L=K===null?null:(G.serialize??String)(K);H2.emit(se,{state:K,query:L});const $={key:se,query:L,options:{history:I.history??G.history??u,shallow:I.shallow??G.shallow??d,scroll:I.scroll??G.scroll??c,startTransition:I.startTransition??G.startTransition??p}};if(I?.limitUrlUpdates?.method==="debounce"||m?.method==="debounce"||G.limitUrlUpdates?.method==="debounce"){$.options.shallow===!0&&console.warn(Sl(422));const ne=I?.limitUrlUpdates?.timeMs??m?.timeMs??G.limitUrlUpdates?.timeMs??hl.timeMs,ie=E2.push($,ne,x,s);de<ne&&(ce=ie,de=ne)}else{const ne=I?.limitUrlUpdates?.timeMs??G?.limitUrlUpdates?.timeMs??m?.timeMs??I.throttleMs??G.throttleMs??v;fe.push(E2.abort(se)),vu.push($,ne),J=!0}}const U=fe.reduce((H,K)=>K(H),J?vu.flush(x,s):vu.getPendingPromise(x));return ce??U},[b,u,d,c,v,m?.method,m?.timeMs,p,S,x.updateUrl,x.getSearchParamsSnapshot,x.rateLimitFactor,s,T]);return[y.useMemo(()=>Wg(_,T),[_,T]),F]}function B2(t,a,o,i,s,u){let c=!1;const d=Object.entries(t).reduce((v,[m,A])=>{const p=a?.[m]??m,C=i[p],b=A.type==="multi"?[]:null,S=C===void 0?(A.type==="multi"?o?.getAll(p):o?.get(p))??b:C;return s&&u&&ty(s[p]??b,S)?(v[m]=u[m]??null,v):(c=!0,v[m]=(lb(S)?null:RA(A.parse,S,p))??null,s&&(s[p]=S),v)},{});if(!c){const v=Object.keys(t),m=Object.keys(u??{});c=v.length!==m.length||v.some(A=>!m.includes(A))}return{state:d,hasChanged:c}}function Wg(t,a){return Object.fromEntries(Object.keys(t).map(o=>[o,t[o]??a[o]??null]))}function wd(t,a={}){const{parse:o,type:i,serialize:s,eq:u,defaultValue:c,...d}=a,[{[t]:v},m]=Ax({[t]:{parse:o??(A=>A),type:i,serialize:s,eq:u,defaultValue:c}},d);return[v,y.useCallback((A,p={})=>m(C=>({[t]:typeof A=="function"?A(C[t]):A}),p),[t,m])]}function TA(t){const[a,o]=y.useState(()=>typeof window<"u"?window.matchMedia(t).matches:!1);return y.useLayoutEffect(()=>{if(typeof window>"u")return;const i=window.matchMedia(t),s=()=>o(i.matches);return i.addEventListener("change",s),()=>i.removeEventListener("change",s)},[t]),a}const Cx=async()=>JSON.stringify(await(await fetch("/.vocs/search-index-8d63ff3e.json")).json()),bx="ENTRIES",MA="KEYS",DA="VALUES",Wt="";class $2{constructor(a,o){const i=a._tree,s=Array.from(i.keys());this.set=a,this._type=o,this._path=s.length>0?[{node:i,keys:s}]:[]}next(){const a=this.dive();return this.backtrack(),a}dive(){if(this._path.length===0)return{done:!0,value:void 0};const{node:a,keys:o}=Qo(this._path);if(Qo(o)===Wt)return{done:!1,value:this.result()};const i=a.get(Qo(o));return this._path.push({node:i,keys:Array.from(i.keys())}),this.dive()}backtrack(){if(this._path.length===0)return;const a=Qo(this._path).keys;a.pop(),!(a.length>0)&&(this._path.pop(),this.backtrack())}key(){return this.set._prefix+this._path.map(({keys:a})=>Qo(a)).filter(a=>a!==Wt).join("")}value(){return Qo(this._path).node.get(Wt)}result(){switch(this._type){case DA:return this.value();case MA:return this.key();default:return[this.key(),this.value()]}}[Symbol.iterator](){return this}}const Qo=t=>t[t.length-1],Ex=(t,a,o)=>{const i=new Map;if(a===void 0)return i;const s=a.length+1,u=s+o,c=new Uint8Array(u*s).fill(o+1);for(let d=0;d<s;++d)c[d]=d;for(let d=1;d<u;++d)c[d*s]=d;return OA(t,a,o,i,c,1,s,""),i},OA=(t,a,o,i,s,u,c,d)=>{const v=u*c;e:for(const m of t.keys())if(m===Wt){const A=s[v-1];A<=o&&i.set(d,[t.get(m),A])}else{let A=u;for(let p=0;p<m.length;++p,++A){const C=m[p],b=c*A,S=b-c;let x=s[b];const w=Math.max(0,A-o-1),D=Math.min(c-1,A+o);for(let T=w;T<D;++T){const R=C!==a[T],_=s[S+T]+ +R,N=s[S+T+1]+1,j=s[b+T]+1,F=s[b+T+1]=Math.min(_,N,j);F<x&&(x=F)}if(x>o)continue e}OA(t.get(m),a,o,i,s,A,c,d+m)}};class Er{constructor(a=new Map,o=""){this._size=void 0,this._tree=a,this._prefix=o}atPrefix(a){if(!a.startsWith(this._prefix))throw new Error("Mismatched prefix");const[o,i]=Tu(this._tree,a.slice(this._prefix.length));if(o===void 0){const[s,u]=_d(i);for(const c of s.keys())if(c!==Wt&&c.startsWith(u)){const d=new Map;return d.set(c.slice(u.length),s.get(c)),new Er(d,a)}}return new Er(o,a)}clear(){this._size=void 0,this._tree.clear()}delete(a){return this._size=void 0,Sx(this._tree,a)}entries(){return new $2(this,bx)}forEach(a){for(const[o,i]of this)a(o,i,this)}fuzzyGet(a,o){return Ex(this._tree,a,o)}get(a){const o=Df(this._tree,a);return o!==void 0?o.get(Wt):void 0}has(a){const o=Df(this._tree,a);return o!==void 0&&o.has(Wt)}keys(){return new $2(this,MA)}set(a,o){if(typeof a!="string")throw new Error("key must be a string");return this._size=void 0,V2(this._tree,a).set(Wt,o),this}get size(){if(this._size)return this._size;this._size=0;const a=this.entries();for(;!a.next().done;)this._size+=1;return this._size}update(a,o){if(typeof a!="string")throw new Error("key must be a string");this._size=void 0;const i=V2(this._tree,a);return i.set(Wt,o(i.get(Wt))),this}fetch(a,o){if(typeof a!="string")throw new Error("key must be a string");this._size=void 0;const i=V2(this._tree,a);let s=i.get(Wt);return s===void 0&&i.set(Wt,s=o()),s}values(){return new $2(this,DA)}[Symbol.iterator](){return this.entries()}static from(a){const o=new Er;for(const[i,s]of a)o.set(i,s);return o}static fromObject(a){return Er.from(Object.entries(a))}}const Tu=(t,a,o=[])=>{if(a.length===0||t==null)return[t,o];for(const i of t.keys())if(i!==Wt&&a.startsWith(i))return o.push([t,i]),Tu(t.get(i),a.slice(i.length),o);return o.push([t,a]),Tu(void 0,"",o)},Df=(t,a)=>{if(a.length===0||t==null)return t;for(const o of t.keys())if(o!==Wt&&a.startsWith(o))return Df(t.get(o),a.slice(o.length))},V2=(t,a)=>{const o=a.length;e:for(let i=0;t&&i<o;){for(const u of t.keys())if(u!==Wt&&a[i]===u[0]){const c=Math.min(o-i,u.length);let d=1;for(;d<c&&a[i+d]===u[d];)++d;const v=t.get(u);if(d===u.length)t=v;else{const m=new Map;m.set(u.slice(d),v),t.set(a.slice(i,i+d),m),t.delete(u),t=m}i+=d;continue e}const s=new Map;return t.set(a.slice(i),s),s}return t},Sx=(t,a)=>{const[o,i]=Tu(t,a);if(o!==void 0){if(o.delete(Wt),o.size===0)NA(i);else if(o.size===1){const[s,u]=o.entries().next().value;LA(i,s,u)}}},NA=t=>{if(t.length===0)return;const[a,o]=_d(t);if(a.delete(o),a.size===0)NA(t.slice(0,-1));else if(a.size===1){const[i,s]=a.entries().next().value;i!==Wt&&LA(t.slice(0,-1),i,s)}},LA=(t,a,o)=>{if(t.length===0)return;const[i,s]=_d(t);i.set(s+a,o),i.delete(s)},_d=t=>t[t.length-1],Rd="or",jA="and",xx="and_not";class ei{constructor(a){if(a?.fields==null)throw new Error('MiniSearch: option "fields" must be provided');const o=a.autoVacuum==null||a.autoVacuum===!0?Y2:a.autoVacuum;this._options={...G2,...a,autoVacuum:o,searchOptions:{...e1,...a.searchOptions||{}},autoSuggestOptions:{...Mx,...a.autoSuggestOptions||{}}},this._index=new Er,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldIds={},this._fieldLength=new Map,this._avgFieldLength=[],this._nextId=0,this._storedFields=new Map,this._dirtCount=0,this._currentVacuum=null,this._enqueuedVacuum=null,this._enqueuedVacuumConditions=Nf,this.addFields(this._options.fields)}add(a){const{extractField:o,stringifyField:i,tokenize:s,processTerm:u,fields:c,idField:d}=this._options,v=o(a,d);if(v==null)throw new Error(`MiniSearch: document does not have ID field "${d}"`);if(this._idToShortId.has(v))throw new Error(`MiniSearch: duplicate ID ${v}`);const m=this.addDocumentId(v);this.saveStoredFields(m,a);for(const A of c){const p=o(a,A);if(p==null)continue;const C=s(i(p,A),A),b=this._fieldIds[A],S=new Set(C).size;this.addFieldLength(m,b,this._documentCount-1,S);for(const x of C){const w=u(x,A);if(Array.isArray(w))for(const D of w)this.addTerm(b,m,D);else w&&this.addTerm(b,m,w)}}}addAll(a){for(const o of a)this.add(o)}addAllAsync(a,o={}){const{chunkSize:i=10}=o,s={chunk:[],promise:Promise.resolve()},{chunk:u,promise:c}=a.reduce(({chunk:d,promise:v},m,A)=>(d.push(m),(A+1)%i===0?{chunk:[],promise:v.then(()=>new Promise(p=>setTimeout(p,0))).then(()=>this.addAll(d))}:{chunk:d,promise:v}),s);return c.then(()=>this.addAll(u))}remove(a){const{tokenize:o,processTerm:i,extractField:s,stringifyField:u,fields:c,idField:d}=this._options,v=s(a,d);if(v==null)throw new Error(`MiniSearch: document does not have ID field "${d}"`);const m=this._idToShortId.get(v);if(m==null)throw new Error(`MiniSearch: cannot remove document with ID ${v}: it is not in the index`);for(const A of c){const p=s(a,A);if(p==null)continue;const C=o(u(p,A),A),b=this._fieldIds[A],S=new Set(C).size;this.removeFieldLength(m,b,this._documentCount,S);for(const x of C){const w=i(x,A);if(Array.isArray(w))for(const D of w)this.removeTerm(b,m,D);else w&&this.removeTerm(b,m,w)}}this._storedFields.delete(m),this._documentIds.delete(m),this._idToShortId.delete(v),this._fieldLength.delete(m),this._documentCount-=1}removeAll(a){if(a)for(const o of a)this.remove(o);else{if(arguments.length>0)throw new Error("Expected documents to be present. Omit the argument to remove all documents.");this._index=new Er,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldLength=new Map,this._avgFieldLength=[],this._storedFields=new Map,this._nextId=0}}discard(a){const o=this._idToShortId.get(a);if(o==null)throw new Error(`MiniSearch: cannot discard document with ID ${a}: it is not in the index`);this._idToShortId.delete(a),this._documentIds.delete(o),this._storedFields.delete(o),(this._fieldLength.get(o)||[]).forEach((i,s)=>{this.removeFieldLength(o,s,this._documentCount,i)}),this._fieldLength.delete(o),this._documentCount-=1,this._dirtCount+=1,this.maybeAutoVacuum()}maybeAutoVacuum(){if(this._options.autoVacuum===!1)return;const{minDirtFactor:a,minDirtCount:o,batchSize:i,batchWait:s}=this._options.autoVacuum;this.conditionalVacuum({batchSize:i,batchWait:s},{minDirtCount:o,minDirtFactor:a})}discardAll(a){const o=this._options.autoVacuum;try{this._options.autoVacuum=!1;for(const i of a)this.discard(i)}finally{this._options.autoVacuum=o}this.maybeAutoVacuum()}replace(a){const{idField:o,extractField:i}=this._options,s=i(a,o);this.discard(s),this.add(a)}vacuum(a={}){return this.conditionalVacuum(a)}conditionalVacuum(a,o){return this._currentVacuum?(this._enqueuedVacuumConditions=this._enqueuedVacuumConditions&&o,this._enqueuedVacuum!=null?this._enqueuedVacuum:(this._enqueuedVacuum=this._currentVacuum.then(()=>{const i=this._enqueuedVacuumConditions;return this._enqueuedVacuumConditions=Nf,this.performVacuuming(a,i)}),this._enqueuedVacuum)):this.vacuumConditionsMet(o)===!1?Promise.resolve():(this._currentVacuum=this.performVacuuming(a),this._currentVacuum)}async performVacuuming(a,o){const i=this._dirtCount;if(this.vacuumConditionsMet(o)){const s=a.batchSize||Of.batchSize,u=a.batchWait||Of.batchWait;let c=1;for(const[d,v]of this._index){for(const[m,A]of v)for(const[p]of A)this._documentIds.has(p)||(A.size<=1?v.delete(m):A.delete(p));this._index.get(d).size===0&&this._index.delete(d),c%s===0&&await new Promise(m=>setTimeout(m,u)),c+=1}this._dirtCount-=i}await null,this._currentVacuum=this._enqueuedVacuum,this._enqueuedVacuum=null}vacuumConditionsMet(a){if(a==null)return!0;let{minDirtCount:o,minDirtFactor:i}=a;return o=o||Y2.minDirtCount,i=i||Y2.minDirtFactor,this.dirtCount>=o&&this.dirtFactor>=i}get isVacuuming(){return this._currentVacuum!=null}get dirtCount(){return this._dirtCount}get dirtFactor(){return this._dirtCount/(1+this._documentCount+this._dirtCount)}has(a){return this._idToShortId.has(a)}getStoredFields(a){const o=this._idToShortId.get(a);if(o!=null)return this._storedFields.get(o)}search(a,o={}){const{searchOptions:i}=this._options,s={...i,...o},u=this.executeQuery(a,o),c=[];for(const[d,{score:v,terms:m,match:A}]of u){const p=m.length||1,C={id:this._documentIds.get(d),score:v*p,terms:Object.keys(A),queryTerms:m,match:A};Object.assign(C,this._storedFields.get(d)),(s.filter==null||s.filter(C))&&c.push(C)}return a===ei.wildcard&&s.boostDocument==null||c.sort(n1),c}autoSuggest(a,o={}){o={...this._options.autoSuggestOptions,...o};const i=new Map;for(const{score:u,terms:c}of this.search(a,o)){const d=c.join(" "),v=i.get(d);v!=null?(v.score+=u,v.count+=1):i.set(d,{score:u,terms:c,count:1})}const s=[];for(const[u,{score:c,terms:d,count:v}]of i)s.push({suggestion:u,terms:d,score:c/v});return s.sort(n1),s}get documentCount(){return this._documentCount}get termCount(){return this._index.size}static loadJSON(a,o){if(o==null)throw new Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJS(JSON.parse(a),o)}static async loadJSONAsync(a,o){if(o==null)throw new Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJSAsync(JSON.parse(a),o)}static getDefault(a){if(G2.hasOwnProperty(a))return q2(G2,a);throw new Error(`MiniSearch: unknown option "${a}"`)}static loadJS(a,o){const{index:i,documentIds:s,fieldLength:u,storedFields:c,serializationVersion:d}=a,v=this.instantiateMiniSearch(a,o);v._documentIds=su(s),v._fieldLength=su(u),v._storedFields=su(c);for(const[m,A]of v._documentIds)v._idToShortId.set(A,m);for(const[m,A]of i){const p=new Map;for(const C of Object.keys(A)){let b=A[C];d===1&&(b=b.ds),p.set(parseInt(C,10),su(b))}v._index.set(m,p)}return v}static async loadJSAsync(a,o){const{index:i,documentIds:s,fieldLength:u,storedFields:c,serializationVersion:d}=a,v=this.instantiateMiniSearch(a,o);v._documentIds=await uu(s),v._fieldLength=await uu(u),v._storedFields=await uu(c);for(const[A,p]of v._documentIds)v._idToShortId.set(p,A);let m=0;for(const[A,p]of i){const C=new Map;for(const b of Object.keys(p)){let S=p[b];d===1&&(S=S.ds),C.set(parseInt(b,10),await uu(S))}++m%1e3===0&&await FA(0),v._index.set(A,C)}return v}static instantiateMiniSearch(a,o){const{documentCount:i,nextId:s,fieldIds:u,averageFieldLength:c,dirtCount:d,serializationVersion:v}=a;if(v!==1&&v!==2)throw new Error("MiniSearch: cannot deserialize an index created with an incompatible version");const m=new ei(o);return m._documentCount=i,m._nextId=s,m._idToShortId=new Map,m._fieldIds=u,m._avgFieldLength=c,m._dirtCount=d||0,m._index=new Er,m}executeQuery(a,o={}){if(a===ei.wildcard)return this.executeWildcardQuery(o);if(typeof a!="string"){const C={...o,...a,queries:void 0},b=a.queries.map(S=>this.executeQuery(S,C));return this.combineResults(b,C.combineWith)}const{tokenize:i,processTerm:s,searchOptions:u}=this._options,c={tokenize:i,processTerm:s,...u,...o},{tokenize:d,processTerm:v}=c,p=d(a).flatMap(C=>v(C)).filter(C=>!!C).map(Tx(c)).map(C=>this.executeQuerySpec(C,c));return this.combineResults(p,c.combineWith)}executeQuerySpec(a,o){const i={...this._options.searchOptions,...o},s=(i.fields||this._options.fields).reduce((x,w)=>({...x,[w]:q2(i.boost,w)||1}),{}),{boostDocument:u,weights:c,maxFuzzy:d,bm25:v}=i,{fuzzy:m,prefix:A}={...e1.weights,...c},p=this._index.get(a.term),C=this.termResults(a.term,a.term,1,a.termBoost,p,s,u,v);let b,S;if(a.prefix&&(b=this._index.atPrefix(a.term)),a.fuzzy){const x=a.fuzzy===!0?.2:a.fuzzy,w=x<1?Math.min(d,Math.round(a.term.length*x)):x;w&&(S=this._index.fuzzyGet(a.term,w))}if(b)for(const[x,w]of b){const D=x.length-a.term.length;if(!D)continue;S?.delete(x);const T=A*x.length/(x.length+.3*D);this.termResults(a.term,x,T,a.termBoost,w,s,u,v,C)}if(S)for(const x of S.keys()){const[w,D]=S.get(x);if(!D)continue;const T=m*x.length/(x.length+D);this.termResults(a.term,x,T,a.termBoost,w,s,u,v,C)}return C}executeWildcardQuery(a){const o=new Map,i={...this._options.searchOptions,...a};for(const[s,u]of this._documentIds){const c=i.boostDocument?i.boostDocument(u,"",this._storedFields.get(s)):1;o.set(s,{score:c,terms:[],match:{}})}return o}combineResults(a,o=Rd){if(a.length===0)return new Map;const i=o.toLowerCase(),s=wx[i];if(!s)throw new Error(`Invalid combination operator: ${o}`);return a.reduce(s)||new Map}toJSON(){const a=[];for(const[o,i]of this._index){const s={};for(const[u,c]of i)s[u]=Object.fromEntries(c);a.push([o,s])}return{documentCount:this._documentCount,nextId:this._nextId,documentIds:Object.fromEntries(this._documentIds),fieldIds:this._fieldIds,fieldLength:Object.fromEntries(this._fieldLength),averageFieldLength:this._avgFieldLength,storedFields:Object.fromEntries(this._storedFields),dirtCount:this._dirtCount,index:a,serializationVersion:2}}termResults(a,o,i,s,u,c,d,v,m=new Map){if(u==null)return m;for(const A of Object.keys(c)){const p=c[A],C=this._fieldIds[A],b=u.get(C);if(b==null)continue;let S=b.size;const x=this._avgFieldLength[C];for(const w of b.keys()){if(!this._documentIds.has(w)){this.removeTerm(C,w,o),S-=1;continue}const D=d?d(this._documentIds.get(w),o,this._storedFields.get(w)):1;if(!D)continue;const T=b.get(w),R=this._fieldLength.get(w)[C],_=Rx(T,S,this._documentCount,R,x,v),N=i*s*p*D*_,j=m.get(w);if(j){j.score+=N,Dx(j.terms,a);const F=q2(j.match,o);F?F.push(A):j.match[o]=[A]}else m.set(w,{score:N,terms:[a],match:{[o]:[A]}})}}return m}addTerm(a,o,i){const s=this._index.fetch(i,a1);let u=s.get(a);if(u==null)u=new Map,u.set(o,1),s.set(a,u);else{const c=u.get(o);u.set(o,(c||0)+1)}}removeTerm(a,o,i){if(!this._index.has(i)){this.warnDocumentChanged(o,a,i);return}const s=this._index.fetch(i,a1),u=s.get(a);u==null||u.get(o)==null?this.warnDocumentChanged(o,a,i):u.get(o)<=1?u.size<=1?s.delete(a):u.delete(o):u.set(o,u.get(o)-1),this._index.get(i).size===0&&this._index.delete(i)}warnDocumentChanged(a,o,i){for(const s of Object.keys(this._fieldIds))if(this._fieldIds[s]===o){this._options.logger("warn",`MiniSearch: document with ID ${this._documentIds.get(a)} has changed before removal: term "${i}" was not present in field "${s}". Removing a document after it has changed can corrupt the index!`,"version_conflict");return}}addDocumentId(a){const o=this._nextId;return this._idToShortId.set(a,o),this._documentIds.set(o,a),this._documentCount+=1,this._nextId+=1,o}addFields(a){for(let o=0;o<a.length;o++)this._fieldIds[a[o]]=o}addFieldLength(a,o,i,s){let u=this._fieldLength.get(a);u==null&&this._fieldLength.set(a,u=[]),u[o]=s;const d=(this._avgFieldLength[o]||0)*i+s;this._avgFieldLength[o]=d/(i+1)}removeFieldLength(a,o,i,s){if(i===1){this._avgFieldLength[o]=0;return}const u=this._avgFieldLength[o]*i-s;this._avgFieldLength[o]=u/(i-1)}saveStoredFields(a,o){const{storeFields:i,extractField:s}=this._options;if(i==null||i.length===0)return;let u=this._storedFields.get(a);u==null&&this._storedFields.set(a,u={});for(const c of i){const d=s(o,c);d!==void 0&&(u[c]=d)}}}ei.wildcard=Symbol("*");const q2=(t,a)=>Object.prototype.hasOwnProperty.call(t,a)?t[a]:void 0,wx={[Rd]:(t,a)=>{for(const o of a.keys()){const i=t.get(o);if(i==null)t.set(o,a.get(o));else{const{score:s,terms:u,match:c}=a.get(o);i.score=i.score+s,i.match=Object.assign(i.match,c),t1(i.terms,u)}}return t},[jA]:(t,a)=>{const o=new Map;for(const i of a.keys()){const s=t.get(i);if(s==null)continue;const{score:u,terms:c,match:d}=a.get(i);t1(s.terms,c),o.set(i,{score:s.score+u,terms:s.terms,match:Object.assign(s.match,d)})}return o},[xx]:(t,a)=>{for(const o of a.keys())t.delete(o);return t}},_x={k:1.2,b:.7,d:.5},Rx=(t,a,o,i,s,u)=>{const{k:c,b:d,d:v}=u;return Math.log(1+(o-a+.5)/(a+.5))*(v+t*(c+1)/(t+c*(1-d+d*i/s)))},Tx=t=>(a,o,i)=>{const s=typeof t.fuzzy=="function"?t.fuzzy(a,o,i):t.fuzzy||!1,u=typeof t.prefix=="function"?t.prefix(a,o,i):t.prefix===!0,c=typeof t.boostTerm=="function"?t.boostTerm(a,o,i):1;return{term:a,fuzzy:s,prefix:u,termBoost:c}},G2={idField:"id",extractField:(t,a)=>t[a],stringifyField:(t,a)=>t.toString(),tokenize:t=>t.split(Ox),processTerm:t=>t.toLowerCase(),fields:void 0,searchOptions:void 0,storeFields:[],logger:(t,a)=>{typeof console?.[t]=="function"&&console[t](a)},autoVacuum:!0},e1={combineWith:Rd,prefix:!1,fuzzy:!1,maxFuzzy:6,boost:{},weights:{fuzzy:.45,prefix:.375},bm25:_x},Mx={combineWith:jA,prefix:(t,a,o)=>a===o.length-1},Of={batchSize:1e3,batchWait:10},Nf={minDirtFactor:.1,minDirtCount:20},Y2={...Of,...Nf},Dx=(t,a)=>{t.includes(a)||t.push(a)},t1=(t,a)=>{for(const o of a)t.includes(o)||t.push(o)},n1=({score:t},{score:a})=>a-t,a1=()=>new Map,su=t=>{const a=new Map;for(const o of Object.keys(t))a.set(parseInt(o,10),t[o]);return a},uu=async t=>{const a=new Map;let o=0;for(const i of Object.keys(t))a.set(parseInt(i,10),t[i]),++o%1e3===0&&await FA(0);return a},FA=t=>new Promise(a=>setTimeout(a,t)),Ox=/[\n\r\p{Z}\p{P}]+/u;let Q2;function kA(){const[t,a]=y.useState();return y.useEffect(()=>{(async()=>{Q2||(Q2=Cx());const o=await Q2,i=ei.loadJSON(o,{fields:["title","titles","text"],searchOptions:{boost:{title:4,text:2,titles:1},fuzzy:.2,prefix:!0},storeFields:["href","html","isPage","text","title","titles"]});a(i)})()},[]),y.useEffect(()=>{},[]),t}var Nx="vocs_DesktopSearch_search",Lx="vocs_DesktopSearch_searchCommand",jx=Symbol.for("react.lazy"),Mu=li[" use ".trim().toString()];function Fx(t){return typeof t=="object"&&t!==null&&"then"in t}function zA(t){return t!=null&&typeof t=="object"&&"$$typeof"in t&&t.$$typeof===jx&&"_payload"in t&&Fx(t._payload)}function kx(t){const a=zx(t),o=y.forwardRef((i,s)=>{let{children:u,...c}=i;zA(u)&&typeof Mu=="function"&&(u=Mu(u._payload));const d=y.Children.toArray(u),v=d.find(Px);if(v){const m=v.props.children,A=d.map(p=>p===v?y.Children.count(m)>1?y.Children.only(null):y.isValidElement(m)?m.props.children:null:p);return g.jsx(a,{...c,ref:s,children:y.isValidElement(m)?y.cloneElement(m,void 0,A):null})}return g.jsx(a,{...c,ref:s,children:u})});return o.displayName=`${t}.Slot`,o}function zx(t){const a=y.forwardRef((o,i)=>{let{children:s,...u}=o;if(zA(s)&&typeof Mu=="function"&&(s=Mu(s._payload)),y.isValidElement(s)){const c=Hx(s),d=Ix(u,s.props);return s.type!==y.Fragment&&(d.ref=i?di(i,c):c),y.cloneElement(s,d)}return y.Children.count(s)>1?y.Children.only(null):null});return a.displayName=`${t}.SlotClone`,a}var Ux=Symbol("radix.slottable");function Px(t){return y.isValidElement(t)&&typeof t.type=="function"&&"__radixId"in t.type&&t.type.__radixId===Ux}function Ix(t,a){const o={...a};for(const i in a){const s=t[i],u=a[i];/^on[A-Z]/.test(i)?s&&u?o[i]=(...d)=>{const v=u(...d);return s(...d),v}:s&&(o[i]=s):i==="style"?o[i]={...s,...u}:i==="className"&&(o[i]=[s,u].filter(Boolean).join(" "))}return{...t,...o}}function Hx(t){let a=Object.getOwnPropertyDescriptor(t.props,"ref")?.get,o=a&&"isReactWarning"in a&&a.isReactWarning;return o?t.ref:(a=Object.getOwnPropertyDescriptor(t,"ref")?.get,o=a&&"isReactWarning"in a&&a.isReactWarning,o?t.props.ref:t.props.ref||t.ref)}var Bx=["a","button","div","form","h2","h3","img","input","label","li","nav","ol","p","select","span","svg","ul"],$x=Bx.reduce((t,a)=>{const o=kx(`Primitive.${a}`),i=y.forwardRef((s,u)=>{const{asChild:c,...d}=s,v=c?o:a;return typeof window<"u"&&(window[Symbol.for("radix-ui")]=!0),g.jsx(v,{...d,ref:u})});return i.displayName=`Primitive.${a}`,{...t,[a]:i}},{}),Vx="Label",UA=y.forwardRef((t,a)=>g.jsx($x.label,{...t,ref:a,onMouseDown:o=>{o.target.closest("button, input, select, textarea")||(t.onMouseDown?.(o),!o.defaultPrevented&&o.detail>1&&o.preventDefault())}}));UA.displayName=Vx;var qx=UA,Eu={exports:{}};var Gx=Eu.exports,r1;function Yx(){return r1||(r1=1,(function(t,a){(function(o,i){t.exports=i()})(Gx,(function(){var o=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(m){return typeof m}:function(m){return m&&typeof Symbol=="function"&&m.constructor===Symbol&&m!==Symbol.prototype?"symbol":typeof m},i=function(m,A){if(!(m instanceof A))throw new TypeError("Cannot call a class as a function")},s=(function(){function m(A,p){for(var C=0;C<p.length;C++){var b=p[C];b.enumerable=b.enumerable||!1,b.configurable=!0,"value"in b&&(b.writable=!0),Object.defineProperty(A,b.key,b)}}return function(A,p,C){return p&&m(A.prototype,p),C&&m(A,C),A}})(),u=Object.assign||function(m){for(var A=1;A<arguments.length;A++){var p=arguments[A];for(var C in p)Object.prototype.hasOwnProperty.call(p,C)&&(m[C]=p[C])}return m},c=(function(){function m(A){var p=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,C=arguments.length>2&&arguments[2]!==void 0?arguments[2]:[],b=arguments.length>3&&arguments[3]!==void 0?arguments[3]:5e3;i(this,m),this.ctx=A,this.iframes=p,this.exclude=C,this.iframesTimeout=b}return s(m,[{key:"getContexts",value:function(){var p=void 0,C=[];return typeof this.ctx>"u"||!this.ctx?p=[]:NodeList.prototype.isPrototypeOf(this.ctx)?p=Array.prototype.slice.call(this.ctx):Array.isArray(this.ctx)?p=this.ctx:typeof this.ctx=="string"?p=Array.prototype.slice.call(document.querySelectorAll(this.ctx)):p=[this.ctx],p.forEach(function(b){var S=C.filter(function(x){return x.contains(b)}).length>0;C.indexOf(b)===-1&&!S&&C.push(b)}),C}},{key:"getIframeContents",value:function(p,C){var b=arguments.length>2&&arguments[2]!==void 0?arguments[2]:function(){},S=void 0;try{var x=p.contentWindow;if(S=x.document,!x||!S)throw new Error("iframe inaccessible")}catch{b()}S&&C(S)}},{key:"isIframeBlank",value:function(p){var C="about:blank",b=p.getAttribute("src").trim(),S=p.contentWindow.location.href;return S===C&&b!==C&&b}},{key:"observeIframeLoad",value:function(p,C,b){var S=this,x=!1,w=null,D=function T(){if(!x){x=!0,clearTimeout(w);try{S.isIframeBlank(p)||(p.removeEventListener("load",T),S.getIframeContents(p,C,b))}catch{b()}}};p.addEventListener("load",D),w=setTimeout(D,this.iframesTimeout)}},{key:"onIframeReady",value:function(p,C,b){try{p.contentWindow.document.readyState==="complete"?this.isIframeBlank(p)?this.observeIframeLoad(p,C,b):this.getIframeContents(p,C,b):this.observeIframeLoad(p,C,b)}catch{b()}}},{key:"waitForIframes",value:function(p,C){var b=this,S=0;this.forEachIframe(p,function(){return!0},function(x){S++,b.waitForIframes(x.querySelector("html"),function(){--S||C()})},function(x){x||C()})}},{key:"forEachIframe",value:function(p,C,b){var S=this,x=arguments.length>3&&arguments[3]!==void 0?arguments[3]:function(){},w=p.querySelectorAll("iframe"),D=w.length,T=0;w=Array.prototype.slice.call(w);var R=function(){--D<=0&&x(T)};D||R(),w.forEach(function(_){m.matches(_,S.exclude)?R():S.onIframeReady(_,function(N){C(_)&&(T++,b(N)),R()},R)})}},{key:"createIterator",value:function(p,C,b){return document.createNodeIterator(p,C,b,!1)}},{key:"createInstanceOnIframe",value:function(p){return new m(p.querySelector("html"),this.iframes)}},{key:"compareNodeIframe",value:function(p,C,b){var S=p.compareDocumentPosition(b),x=Node.DOCUMENT_POSITION_PRECEDING;if(S&x)if(C!==null){var w=C.compareDocumentPosition(b),D=Node.DOCUMENT_POSITION_FOLLOWING;if(w&D)return!0}else return!0;return!1}},{key:"getIteratorNode",value:function(p){var C=p.previousNode(),b=void 0;return C===null?b=p.nextNode():b=p.nextNode()&&p.nextNode(),{prevNode:C,node:b}}},{key:"checkIframeFilter",value:function(p,C,b,S){var x=!1,w=!1;return S.forEach(function(D,T){D.val===b&&(x=T,w=D.handled)}),this.compareNodeIframe(p,C,b)?(x===!1&&!w?S.push({val:b,handled:!0}):x!==!1&&!w&&(S[x].handled=!0),!0):(x===!1&&S.push({val:b,handled:!1}),!1)}},{key:"handleOpenIframes",value:function(p,C,b,S){var x=this;p.forEach(function(w){w.handled||x.getIframeContents(w.val,function(D){x.createInstanceOnIframe(D).forEachNode(C,b,S)})})}},{key:"iterateThroughNodes",value:function(p,C,b,S,x){for(var w=this,D=this.createIterator(C,p,S),T=[],R=[],_=void 0,N=void 0,j=function(){var O=w.getIteratorNode(D);return N=O.prevNode,_=O.node,_};j();)this.iframes&&this.forEachIframe(C,function(F){return w.checkIframeFilter(_,N,F,T)},function(F){w.createInstanceOnIframe(F).forEachNode(p,function(O){return R.push(O)},S)}),R.push(_);R.forEach(function(F){b(F)}),this.iframes&&this.handleOpenIframes(T,p,b,S),x()}},{key:"forEachNode",value:function(p,C,b){var S=this,x=arguments.length>3&&arguments[3]!==void 0?arguments[3]:function(){},w=this.getContexts(),D=w.length;D||x(),w.forEach(function(T){var R=function(){S.iterateThroughNodes(p,T,C,b,function(){--D<=0&&x()})};S.iframes?S.waitForIframes(T,R):R()})}}],[{key:"matches",value:function(p,C){var b=typeof C=="string"?[C]:C,S=p.matches||p.matchesSelector||p.msMatchesSelector||p.mozMatchesSelector||p.oMatchesSelector||p.webkitMatchesSelector;if(S){var x=!1;return b.every(function(w){return S.call(p,w)?(x=!0,!1):!0}),x}else return!1}}]),m})(),d=(function(){function m(A){i(this,m),this.ctx=A,this.ie=!1;var p=window.navigator.userAgent;(p.indexOf("MSIE")>-1||p.indexOf("Trident")>-1)&&(this.ie=!0)}return s(m,[{key:"log",value:function(p){var C=arguments.length>1&&arguments[1]!==void 0?arguments[1]:"debug",b=this.opt.log;this.opt.debug&&(typeof b>"u"?"undefined":o(b))==="object"&&typeof b[C]=="function"&&b[C]("mark.js: "+p)}},{key:"escapeStr",value:function(p){return p.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}},{key:"createRegExp",value:function(p){return this.opt.wildcards!=="disabled"&&(p=this.setupWildcardsRegExp(p)),p=this.escapeStr(p),Object.keys(this.opt.synonyms).length&&(p=this.createSynonymsRegExp(p)),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(p=this.setupIgnoreJoinersRegExp(p)),this.opt.diacritics&&(p=this.createDiacriticsRegExp(p)),p=this.createMergedBlanksRegExp(p),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(p=this.createJoinersRegExp(p)),this.opt.wildcards!=="disabled"&&(p=this.createWildcardsRegExp(p)),p=this.createAccuracyRegExp(p),p}},{key:"createSynonymsRegExp",value:function(p){var C=this.opt.synonyms,b=this.opt.caseSensitive?"":"i",S=this.opt.ignoreJoiners||this.opt.ignorePunctuation.length?"\0":"";for(var x in C)if(C.hasOwnProperty(x)){var w=C[x],D=this.opt.wildcards!=="disabled"?this.setupWildcardsRegExp(x):this.escapeStr(x),T=this.opt.wildcards!=="disabled"?this.setupWildcardsRegExp(w):this.escapeStr(w);D!==""&&T!==""&&(p=p.replace(new RegExp("("+this.escapeStr(D)+"|"+this.escapeStr(T)+")","gm"+b),S+("("+this.processSynomyms(D)+"|")+(this.processSynomyms(T)+")")+S))}return p}},{key:"processSynomyms",value:function(p){return(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(p=this.setupIgnoreJoinersRegExp(p)),p}},{key:"setupWildcardsRegExp",value:function(p){return p=p.replace(/(?:\\)*\?/g,function(C){return C.charAt(0)==="\\"?"?":""}),p.replace(/(?:\\)*\*/g,function(C){return C.charAt(0)==="\\"?"*":""})}},{key:"createWildcardsRegExp",value:function(p){var C=this.opt.wildcards==="withSpaces";return p.replace(/\u0001/g,C?"[\\S\\s]?":"\\S?").replace(/\u0002/g,C?"[\\S\\s]*?":"\\S*")}},{key:"setupIgnoreJoinersRegExp",value:function(p){return p.replace(/[^(|)\\]/g,function(C,b,S){var x=S.charAt(b+1);return/[(|)\\]/.test(x)||x===""?C:C+"\0"})}},{key:"createJoinersRegExp",value:function(p){var C=[],b=this.opt.ignorePunctuation;return Array.isArray(b)&&b.length&&C.push(this.escapeStr(b.join(""))),this.opt.ignoreJoiners&&C.push("\\u00ad\\u200b\\u200c\\u200d"),C.length?p.split(/\u0000+/).join("["+C.join("")+"]*"):p}},{key:"createDiacriticsRegExp",value:function(p){var C=this.opt.caseSensitive?"":"i",b=this.opt.caseSensitive?["aàáảãạăằắẳẵặâầấẩẫậäåāą","AÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćč","CÇĆČ","dđď","DĐĎ","eèéẻẽẹêềếểễệëěēę","EÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïī","IÌÍỈĨỊÎÏĪ","lł","LŁ","nñňń","NÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøō","OÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rř","RŘ","sšśșş","SŠŚȘŞ","tťțţ","TŤȚŢ","uùúủũụưừứửữựûüůū","UÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿ","YÝỲỶỸỴŸ","zžżź","ZŽŻŹ"]:["aàáảãạăằắẳẵặâầấẩẫậäåāąAÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćčCÇĆČ","dđďDĐĎ","eèéẻẽẹêềếểễệëěēęEÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïīIÌÍỈĨỊÎÏĪ","lłLŁ","nñňńNÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøōOÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rřRŘ","sšśșşSŠŚȘŞ","tťțţTŤȚŢ","uùúủũụưừứửữựûüůūUÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿYÝỲỶỸỴŸ","zžżźZŽŻŹ"],S=[];return p.split("").forEach(function(x){b.every(function(w){if(w.indexOf(x)!==-1){if(S.indexOf(w)>-1)return!1;p=p.replace(new RegExp("["+w+"]","gm"+C),"["+w+"]"),S.push(w)}return!0})}),p}},{key:"createMergedBlanksRegExp",value:function(p){return p.replace(/[\s]+/gmi,"[\\s]+")}},{key:"createAccuracyRegExp",value:function(p){var C=this,b="!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~¡¿",S=this.opt.accuracy,x=typeof S=="string"?S:S.value,w=typeof S=="string"?[]:S.limiters,D="";switch(w.forEach(function(T){D+="|"+C.escapeStr(T)}),x){case"partially":default:return"()("+p+")";case"complementary":return D="\\s"+(D||this.escapeStr(b)),"()([^"+D+"]*"+p+"[^"+D+"]*)";case"exactly":return"(^|\\s"+D+")("+p+")(?=$|\\s"+D+")"}}},{key:"getSeparatedKeywords",value:function(p){var C=this,b=[];return p.forEach(function(S){C.opt.separateWordSearch?S.split(" ").forEach(function(x){x.trim()&&b.indexOf(x)===-1&&b.push(x)}):S.trim()&&b.indexOf(S)===-1&&b.push(S)}),{keywords:b.sort(function(S,x){return x.length-S.length}),length:b.length}}},{key:"isNumeric",value:function(p){return Number(parseFloat(p))==p}},{key:"checkRanges",value:function(p){var C=this;if(!Array.isArray(p)||Object.prototype.toString.call(p[0])!=="[object Object]")return this.log("markRanges() will only accept an array of objects"),this.opt.noMatch(p),[];var b=[],S=0;return p.sort(function(x,w){return x.start-w.start}).forEach(function(x){var w=C.callNoMatchOnInvalidRanges(x,S),D=w.start,T=w.end,R=w.valid;R&&(x.start=D,x.length=T-D,b.push(x),S=T)}),b}},{key:"callNoMatchOnInvalidRanges",value:function(p,C){var b=void 0,S=void 0,x=!1;return p&&typeof p.start<"u"?(b=parseInt(p.start,10),S=b+parseInt(p.length,10),this.isNumeric(p.start)&&this.isNumeric(p.length)&&S-C>0&&S-b>0?x=!0:(this.log("Ignoring invalid or overlapping range: "+(""+JSON.stringify(p))),this.opt.noMatch(p))):(this.log("Ignoring invalid range: "+JSON.stringify(p)),this.opt.noMatch(p)),{start:b,end:S,valid:x}}},{key:"checkWhitespaceRanges",value:function(p,C,b){var S=void 0,x=!0,w=b.length,D=C-w,T=parseInt(p.start,10)-D;return T=T>w?w:T,S=T+parseInt(p.length,10),S>w&&(S=w,this.log("End range automatically set to the max value of "+w)),T<0||S-T<0||T>w||S>w?(x=!1,this.log("Invalid range: "+JSON.stringify(p)),this.opt.noMatch(p)):b.substring(T,S).replace(/\s+/g,"")===""&&(x=!1,this.log("Skipping whitespace only range: "+JSON.stringify(p)),this.opt.noMatch(p)),{start:T,end:S,valid:x}}},{key:"getTextNodes",value:function(p){var C=this,b="",S=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,function(x){S.push({start:b.length,end:(b+=x.textContent).length,node:x})},function(x){return C.matchesExclude(x.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},function(){p({value:b,nodes:S})})}},{key:"matchesExclude",value:function(p){return c.matches(p,this.opt.exclude.concat(["script","style","title","head","html"]))}},{key:"wrapRangeInTextNode",value:function(p,C,b){var S=this.opt.element?this.opt.element:"mark",x=p.splitText(C),w=x.splitText(b-C),D=document.createElement(S);return D.setAttribute("data-markjs","true"),this.opt.className&&D.setAttribute("class",this.opt.className),D.textContent=x.textContent,x.parentNode.replaceChild(D,x),w}},{key:"wrapRangeInMappedTextNode",value:function(p,C,b,S,x){var w=this;p.nodes.every(function(D,T){var R=p.nodes[T+1];if(typeof R>"u"||R.start>C){if(!S(D.node))return!1;var _=C-D.start,N=(b>D.end?D.end:b)-D.start,j=p.value.substr(0,D.start),F=p.value.substr(N+D.start);if(D.node=w.wrapRangeInTextNode(D.node,_,N),p.value=j+F,p.nodes.forEach(function(O,I){I>=T&&(p.nodes[I].start>0&&I!==T&&(p.nodes[I].start-=N),p.nodes[I].end-=N)}),b-=N,x(D.node.previousSibling,D.start),b>D.end)C=D.end;else return!1}return!0})}},{key:"wrapMatches",value:function(p,C,b,S,x){var w=this,D=C===0?0:C+1;this.getTextNodes(function(T){T.nodes.forEach(function(R){R=R.node;for(var _=void 0;(_=p.exec(R.textContent))!==null&&_[D]!=="";)if(b(_[D],R)){var N=_.index;if(D!==0)for(var j=1;j<D;j++)N+=_[j].length;R=w.wrapRangeInTextNode(R,N,N+_[D].length),S(R.previousSibling),p.lastIndex=0}}),x()})}},{key:"wrapMatchesAcrossElements",value:function(p,C,b,S,x){var w=this,D=C===0?0:C+1;this.getTextNodes(function(T){for(var R=void 0;(R=p.exec(T.value))!==null&&R[D]!=="";){var _=R.index;if(D!==0)for(var N=1;N<D;N++)_+=R[N].length;var j=_+R[D].length;w.wrapRangeInMappedTextNode(T,_,j,function(F){return b(R[D],F)},function(F,O){p.lastIndex=O,S(F)})}x()})}},{key:"wrapRangeFromIndex",value:function(p,C,b,S){var x=this;this.getTextNodes(function(w){var D=w.value.length;p.forEach(function(T,R){var _=x.checkWhitespaceRanges(T,D,w.value),N=_.start,j=_.end,F=_.valid;F&&x.wrapRangeInMappedTextNode(w,N,j,function(O){return C(O,T,w.value.substring(N,j),R)},function(O){b(O,T)})}),S()})}},{key:"unwrapMatches",value:function(p){for(var C=p.parentNode,b=document.createDocumentFragment();p.firstChild;)b.appendChild(p.removeChild(p.firstChild));C.replaceChild(b,p),this.ie?this.normalizeTextNode(C):C.normalize()}},{key:"normalizeTextNode",value:function(p){if(p){if(p.nodeType===3)for(;p.nextSibling&&p.nextSibling.nodeType===3;)p.nodeValue+=p.nextSibling.nodeValue,p.parentNode.removeChild(p.nextSibling);else this.normalizeTextNode(p.firstChild);this.normalizeTextNode(p.nextSibling)}}},{key:"markRegExp",value:function(p,C){var b=this;this.opt=C,this.log('Searching with expression "'+p+'"');var S=0,x="wrapMatches",w=function(T){S++,b.opt.each(T)};this.opt.acrossElements&&(x="wrapMatchesAcrossElements"),this[x](p,this.opt.ignoreGroups,function(D,T){return b.opt.filter(T,D,S)},w,function(){S===0&&b.opt.noMatch(p),b.opt.done(S)})}},{key:"mark",value:function(p,C){var b=this;this.opt=C;var S=0,x="wrapMatches",w=this.getSeparatedKeywords(typeof p=="string"?[p]:p),D=w.keywords,T=w.length,R=this.opt.caseSensitive?"":"i",_=function N(j){var F=new RegExp(b.createRegExp(j),"gm"+R),O=0;b.log('Searching with expression "'+F+'"'),b[x](F,1,function(I,re){return b.opt.filter(re,j,S,O)},function(I){O++,S++,b.opt.each(I)},function(){O===0&&b.opt.noMatch(j),D[T-1]===j?b.opt.done(S):N(D[D.indexOf(j)+1])})};this.opt.acrossElements&&(x="wrapMatchesAcrossElements"),T===0?this.opt.done(S):_(D[0])}},{key:"markRanges",value:function(p,C){var b=this;this.opt=C;var S=0,x=this.checkRanges(p);x&&x.length?(this.log("Starting to mark with the following ranges: "+JSON.stringify(x)),this.wrapRangeFromIndex(x,function(w,D,T,R){return b.opt.filter(w,D,T,R)},function(w,D){S++,b.opt.each(w,D)},function(){b.opt.done(S)})):this.opt.done(S)}},{key:"unmark",value:function(p){var C=this;this.opt=p;var b=this.opt.element?this.opt.element:"*";b+="[data-markjs]",this.opt.className&&(b+="."+this.opt.className),this.log('Removal selector "'+b+'"'),this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT,function(S){C.unwrapMatches(S)},function(S){var x=c.matches(S,b),w=C.matchesExclude(S);return!x||w?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},this.opt.done)}},{key:"opt",set:function(p){this._opt=u({},{element:"",className:"",exclude:[],iframes:!1,iframesTimeout:5e3,separateWordSearch:!0,diacritics:!0,synonyms:{},accuracy:"partially",acrossElements:!1,caseSensitive:!1,ignoreJoiners:!1,ignoreGroups:0,ignorePunctuation:[],wildcards:"disabled",each:function(){},noMatch:function(){},filter:function(){return!0},done:function(){},debug:!1,log:window.console},p)},get:function(){return this._opt}},{key:"iterator",get:function(){return new c(this.ctx,this.opt.iframes,this.opt.exclude,this.opt.iframesTimeout)}}]),m})();function v(m){var A=this,p=new d(m);return this.mark=function(C,b){return p.mark(C,b),A},this.markRegExp=function(C,b){return p.markRegExp(C,b),A},this.markRanges=function(C,b){return p.markRanges(C,b),A},this.unmark=function(C){return p.unmark(C),A},this}return v}))})(Eu)),Eu.exports}var Qx=Yx();const Kx=El(Qx);function Xx(t,a){const[o,i]=y.useState(t);return y.useEffect(()=>{const s=setTimeout(()=>i(t),a);return()=>{clearTimeout(s)}},[t,a]),o}function PA(t,a){const[o,i]=y.useState();y.useEffect(()=>{const u=Zx(t);i(typeof u>"u"||u===null?a:u)},[a,t]);const s=y.useCallback(u=>{i(c=>{let d;typeof u=="function"?d=u(c):d=u;try{localStorage.setItem(t,JSON.stringify(d))}catch{}return d})},[t]);return[o,s]}function Zx(t){try{const a=localStorage.getItem(t);return typeof a=="string"?JSON.parse(a):void 0}catch{return}}function Jx(t,a){const[o,i]=y.useState();y.useEffect(()=>{const u=Wx(t);i(typeof u>"u"||u===null?typeof a=="function"?a():a:u)},[a,t]);const s=y.useCallback(u=>{i(c=>{let d;typeof u=="function"?d=u(c):d=u;try{sessionStorage.setItem(t,JSON.stringify(d))}catch{}return d})},[t]);return[o,s]}function Wx(t){try{const a=sessionStorage.getItem(t);return typeof a=="string"?JSON.parse(a):void 0}catch{return}}var IA="vocs_utils_visuallyHidden",e5="vocs_KeyboardShortcut",t5="vocs_KeyboardShortcut_kbdGroup",n5="vocs_Kbd";function HA(t){return g.jsx("kbd",{...t,className:me(t.className,n5)})}function Zo(t){const{description:a,keys:o}=t;return g.jsxs("span",{className:e5,children:[a,g.jsx("span",{className:t5,children:o.map(i=>g.jsx(HA,{children:i},i))})]})}var a5="vocs_SearchDialog",r5="vocs_SearchDialog_overlay",o5="vocs_SearchDialog_searchBox",i5="vocs_SearchDialog_searchInput",cu="vocs_SearchDialog_searchInputIcon",l5="vocs_SearchDialog_searchInputIconDesktop",s5="vocs_SearchDialog_searchInputIconMobile",u5="vocs_SearchDialog_results",c5="vocs_SearchDialog_result",f5="vocs_SearchDialog_resultSelected",o1="vocs_SearchDialog_resultIcon",d5="vocs_SearchDialog_titles",i1="vocs_SearchDialog_title",h5="vocs_SearchDialog_titleIcon",p5="vocs_SearchDialog_content",l1="vocs_SearchDialog_excerpt",m5="vocs_SearchDialog_searchShortcuts";function BA(t){const{search:a}=Ot(),o=ld(),i=y.useRef(null),s=y.useRef(null),[u,c]=wd("q",{defaultValue:""}),[d,v]=Jx("filterText",u),m=Xx(d,200);y.useEffect(()=>{u&&v(u)},[u,v]),y.useEffect(()=>{c(t.open?d??"":"")},[d,c,t.open]);const A=kA(),[p,C]=y.useState(-1),[b,S]=y.useState(!1),[x,w]=PA("showDetailView",!0),D=y.useMemo(()=>A?m?(C(0),A.search(m,a).slice(0,16)):(C(-1),[]):[],[A,a,m]),T=D.length,R=D[p],_=y.useCallback(()=>{if(!s.current)return;const N=new Set;for(const O of D)for(const I in O.match)N.add(I);const j=new Kx(s.current);j.unmark({done(){j?.markRegExp(v5(N))}});const F=s.current.querySelectorAll(`.${l1}`);for(const O of F)O.querySelector('mark[data-markjs="true"]')?.scrollIntoView({block:"center"});s.current?.firstElementChild?.scrollIntoView({block:"start"})},[D]);return y.useEffect(()=>{if(!t.open)return;function N(j){switch(j.key){case"ArrowDown":{j.preventDefault(),C(F=>{let O=F+1;return O>=T&&(O=0),s.current?.children[O]?.scrollIntoView({block:"nearest"}),O}),S(!0);break}case"ArrowUp":{j.preventDefault(),C(F=>{let O=F-1;return O<0&&(O=T-1),s.current?.children[O]?.scrollIntoView({block:"nearest"}),O}),S(!0);break}case"Backspace":{if(!j.metaKey)return;j.preventDefault(),v(""),i.current?.focus();break}case"Enter":{if(j.target instanceof HTMLButtonElement&&j.target.type!=="submit"||!R)return;j.preventDefault(),o(R.href),t.onClose();break}}}return window.addEventListener("keydown",N),()=>{window.removeEventListener("keydown",N)}},[o,T,R,t.open,t.onClose,v,t]),y.useEffect(()=>{m!==""&&s.current&&_()},[_,m]),g.jsxs(px,{children:[g.jsx(mx,{className:r5}),g.jsxs(vx,{onOpenAutoFocus:N=>{i.current&&(N.preventDefault(),i.current.focus()),_()},onCloseAutoFocus:()=>{C(0)},className:a5,"aria-describedby":void 0,children:[g.jsx(gx,{className:IA,children:"Search"}),g.jsxs("form",{className:o5,children:[g.jsx("button",{"aria-label":"Close search dialog",type:"button",onClick:()=>t.onClose(),className:s5,children:g.jsx(x8,{className:cu,height:20,width:20})}),g.jsx(qx,{htmlFor:"search-input",children:g.jsx(vd,{"aria-label":"Search",className:me(cu,l5),height:20,width:20})}),g.jsx("input",{ref:i,tabIndex:0,className:i5,id:"search-input",onChange:N=>v(N.target.value),placeholder:"Search",type:"search",value:d}),g.jsx("button",{"aria-label":"Toggle detail view",type:"button",onClick:()=>w(N=>!N),children:g.jsx(N8,{className:cu,height:20,width:20})}),g.jsx("button",{"aria-label":"Reset search",type:"button",className:cu,onClick:()=>{v(""),i.current?.focus()},children:"⌫"})]}),g.jsxs("ul",{className:u5,role:D.length?"listbox":void 0,onMouseMove:()=>S(!1),ref:s,children:[m&&D.length===0&&g.jsxs("li",{children:['No results for "',g.jsx("span",{children:m}),'"']}),D.map((N,j)=>g.jsx("li",{className:me(c5,j===p&&f5),"aria-selected":j===p,"aria-label":[...N.titles.filter(F=>!!F),N.title].join(" > "),children:g.jsxs(ci,{to:N.href,onClick:F=>{F.metaKey||t.onClose()},onMouseEnter:()=>!b&&C(j),onFocus:()=>C(j),children:[g.jsxs("div",{className:d5,children:[N.isPage?g.jsx(D8,{className:o1}):g.jsx("span",{className:o1,children:"#"}),N.titles.filter(F=>!!F).map(F=>g.jsxs("span",{className:i1,children:[g.jsx("span",{dangerouslySetInnerHTML:{__html:F}}),g.jsx(_8,{className:h5})]},F)),g.jsx("span",{className:i1,children:g.jsx("span",{dangerouslySetInnerHTML:{__html:N.title}})})]}),x&&N.text?.trim()&&g.jsx("div",{className:l1,children:g.jsx(Xy,{className:p5,children:g.jsx("div",{dangerouslySetInnerHTML:{__html:N.html}})})})]})},N.id))]}),g.jsxs("div",{className:m5,children:[g.jsx(Zo,{description:"Navigate",keys:["↑","↓"]}),g.jsx(Zo,{description:"Select",keys:["enter"]}),g.jsx(Zo,{description:"Close",keys:["esc"]}),g.jsx(Zo,{description:"Reset",keys:["⌘","⌫"]})]})]})]})}function v5(t){return new RegExp([...t].sort((a,o)=>o.length-a.length).map(a=>`(${a.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")})`).join("|"),"gi")}function g5(){kA();const[t]=wd("q",{defaultValue:""}),[a,o]=y.useState(!1),i=TA("(min-width: 1080px)");return y.useEffect(()=>{i&&t&&o(!0)},[i,t]),y.useEffect(()=>{function s(u){const c=document.activeElement instanceof HTMLElement&&(["input","select","textarea"].includes(document.activeElement.tagName.toLowerCase())||document.activeElement.isContentEditable);u.key==="/"&&!a&&!c?(u.preventDefault(),o(!0)):u.metaKey===!0&&u.key==="k"&&(u.preventDefault(),o(d=>!d))}return window.addEventListener("keydown",s),()=>{window.removeEventListener("keydown",s)}},[a]),g.jsxs(wA,{open:a,onOpenChange:o,children:[g.jsx(_A,{asChild:!0,children:g.jsxs("button",{className:Nx,type:"button",children:[g.jsx(vd,{style:{marginTop:2}}),"Search...",g.jsx("div",{className:Lx,children:g.jsx("div",{style:{background:"currentColor",transform:"rotate(45deg)",width:1.5,borderRadius:2,height:"100%"}})})]})}),i&&g.jsx(BA,{open:a,onClose:()=>o(!1)})]})}var y5="vocs_DesktopTopNav",A5="vocs_DesktopTopNav_withLogo",C5="vocs_DesktopTopNav_content",b5="vocs_DesktopTopNav_curtain",E5="vocs_DesktopTopNav_group",s1="vocs_DesktopTopNav_item",S5="vocs_DesktopTopNav_logo",x5="vocs_DesktopTopNav_logoWrapper",u1="vocs_DesktopTopNav_section",w5=y.createContext(void 0);function Ml(t){const a=y.useContext(w5);return t||a||"ltr"}function Dl(t){const a=t+"CollectionProvider",[o,i]=ra(a),[s,u]=o(a,{collectionRef:{current:null},itemMap:new Map}),c=x=>{const{scope:w,children:D}=x,T=gt.useRef(null),R=gt.useRef(new Map).current;return g.jsx(s,{scope:w,itemMap:R,collectionRef:T,children:D})};c.displayName=a;const d=t+"CollectionSlot",v=ai(d),m=gt.forwardRef((x,w)=>{const{scope:D,children:T}=x,R=u(d,D),_=yt(w,R.collectionRef);return g.jsx(v,{ref:_,children:T})});m.displayName=d;const A=t+"CollectionItemSlot",p="data-radix-collection-item",C=ai(A),b=gt.forwardRef((x,w)=>{const{scope:D,children:T,...R}=x,_=gt.useRef(null),N=yt(w,_),j=u(A,D);return gt.useEffect(()=>(j.itemMap.set(_,{ref:_,...R}),()=>{j.itemMap.delete(_)})),g.jsx(C,{[p]:"",ref:N,children:T})});b.displayName=A;function S(x){const w=u(t+"CollectionConsumer",x);return gt.useCallback(()=>{const T=w.collectionRef.current;if(!T)return[];const R=Array.from(T.querySelectorAll(`[${p}]`));return Array.from(w.itemMap.values()).sort((j,F)=>R.indexOf(j.ref.current)-R.indexOf(F.ref.current))},[w.collectionRef,w.itemMap])}return[{Provider:c,Slot:m,ItemSlot:b},S,i]}function _5(t){const a=y.useRef({value:t,previous:t});return y.useMemo(()=>(a.current.value!==t&&(a.current.previous=a.current.value,a.current.value=t),a.current.previous),[t])}var R5=Object.freeze({position:"absolute",border:0,width:1,height:1,padding:0,margin:-1,overflow:"hidden",clip:"rect(0, 0, 0, 0)",whiteSpace:"nowrap",wordWrap:"normal"}),T5="VisuallyHidden",$A=y.forwardRef((t,a)=>g.jsx(ke.span,{...t,ref:a,style:{...R5,...t.style}}));$A.displayName=T5;var M5=$A,ro="NavigationMenu",[Td,VA,D5]=Dl(ro),[Lf,O5,N5]=Dl(ro),[Md]=ra(ro,[D5,N5]),[L5,Qn]=Md(ro),[j5,F5]=Md(ro),qA=y.forwardRef((t,a)=>{const{__scopeNavigationMenu:o,value:i,onValueChange:s,defaultValue:u,delayDuration:c=200,skipDelayDuration:d=300,orientation:v="horizontal",dir:m,...A}=t,[p,C]=y.useState(null),b=yt(a,I=>C(I)),S=Ml(m),x=y.useRef(0),w=y.useRef(0),D=y.useRef(0),[T,R]=y.useState(!0),[_,N]=Ca({prop:i,onChange:I=>{const re=I!=="",pe=d>0;re?(window.clearTimeout(D.current),pe&&R(!1)):(window.clearTimeout(D.current),D.current=window.setTimeout(()=>R(!0),d)),s?.(I)},defaultProp:u??"",caller:ro}),j=y.useCallback(()=>{window.clearTimeout(w.current),w.current=window.setTimeout(()=>N(""),150)},[N]),F=y.useCallback(I=>{window.clearTimeout(w.current),N(I)},[N]),O=y.useCallback(I=>{_===I?window.clearTimeout(w.current):x.current=window.setTimeout(()=>{window.clearTimeout(w.current),N(I)},c)},[_,N,c]);return y.useEffect(()=>()=>{window.clearTimeout(x.current),window.clearTimeout(w.current),window.clearTimeout(D.current)},[]),g.jsx(GA,{scope:o,isRootMenu:!0,value:_,dir:S,orientation:v,rootNavigationMenu:p,onTriggerEnter:I=>{window.clearTimeout(x.current),T?O(I):F(I)},onTriggerLeave:()=>{window.clearTimeout(x.current),j()},onContentEnter:()=>window.clearTimeout(w.current),onContentLeave:j,onItemSelect:I=>{N(re=>re===I?"":I)},onItemDismiss:()=>N(""),children:g.jsx(ke.nav,{"aria-label":"Main","data-orientation":v,dir:S,...A,ref:b})})});qA.displayName=ro;var jf="NavigationMenuSub",k5=y.forwardRef((t,a)=>{const{__scopeNavigationMenu:o,value:i,onValueChange:s,defaultValue:u,orientation:c="horizontal",...d}=t,v=Qn(jf,o),[m,A]=Ca({prop:i,onChange:s,defaultProp:u??"",caller:jf});return g.jsx(GA,{scope:o,isRootMenu:!1,value:m,dir:v.dir,orientation:c,rootNavigationMenu:v.rootNavigationMenu,onTriggerEnter:p=>A(p),onItemSelect:p=>A(p),onItemDismiss:()=>A(""),children:g.jsx(ke.div,{"data-orientation":c,...d,ref:a})})});k5.displayName=jf;var GA=t=>{const{scope:a,isRootMenu:o,rootNavigationMenu:i,dir:s,orientation:u,children:c,value:d,onItemSelect:v,onItemDismiss:m,onTriggerEnter:A,onTriggerLeave:p,onContentEnter:C,onContentLeave:b}=t,[S,x]=y.useState(null),[w,D]=y.useState(new Map),[T,R]=y.useState(null);return g.jsx(L5,{scope:a,isRootMenu:o,rootNavigationMenu:i,value:d,previousValue:_5(d),baseId:$n(),dir:s,orientation:u,viewport:S,onViewportChange:x,indicatorTrack:T,onIndicatorTrackChange:R,onTriggerEnter:on(A),onTriggerLeave:on(p),onContentEnter:on(C),onContentLeave:on(b),onItemSelect:on(v),onItemDismiss:on(m),onViewportContentChange:y.useCallback((_,N)=>{D(j=>(j.set(_,N),new Map(j)))},[]),onViewportContentRemove:y.useCallback(_=>{D(N=>N.has(_)?(N.delete(_),new Map(N)):N)},[]),children:g.jsx(Td.Provider,{scope:a,children:g.jsx(j5,{scope:a,items:w,children:c})})})},YA="NavigationMenuList",QA=y.forwardRef((t,a)=>{const{__scopeNavigationMenu:o,...i}=t,s=Qn(YA,o),u=g.jsx(ke.ul,{"data-orientation":s.orientation,...i,ref:a});return g.jsx(ke.div,{style:{position:"relative"},ref:s.onIndicatorTrackChange,children:g.jsx(Td.Slot,{scope:o,children:s.isRootMenu?g.jsx(n3,{asChild:!0,children:u}):u})})});QA.displayName=YA;var KA="NavigationMenuItem",[z5,XA]=Md(KA),ZA=y.forwardRef((t,a)=>{const{__scopeNavigationMenu:o,value:i,...s}=t,u=$n(),c=i||u||"LEGACY_REACT_AUTO_VALUE",d=y.useRef(null),v=y.useRef(null),m=y.useRef(null),A=y.useRef(()=>{}),p=y.useRef(!1),C=y.useCallback((S="start")=>{if(d.current){A.current();const x=kf(d.current);x.length&&Nd(S==="start"?x:x.reverse())}},[]),b=y.useCallback(()=>{if(d.current){const S=kf(d.current);S.length&&(A.current=G5(S))}},[]);return g.jsx(z5,{scope:o,value:c,triggerRef:v,contentRef:d,focusProxyRef:m,wasEscapeCloseRef:p,onEntryKeyDown:C,onFocusProxyEnter:C,onRootContentClose:b,onContentFocusOutside:b,children:g.jsx(ke.li,{...s,ref:a})})});ZA.displayName=KA;var Ff="NavigationMenuTrigger",JA=y.forwardRef((t,a)=>{const{__scopeNavigationMenu:o,disabled:i,...s}=t,u=Qn(Ff,t.__scopeNavigationMenu),c=XA(Ff,t.__scopeNavigationMenu),d=y.useRef(null),v=yt(d,c.triggerRef,a),m=r3(u.baseId,c.value),A=o3(u.baseId,c.value),p=y.useRef(!1),C=y.useRef(!1),b=c.value===u.value;return g.jsxs(g.Fragment,{children:[g.jsx(Td.ItemSlot,{scope:o,value:c.value,children:g.jsx(a3,{asChild:!0,children:g.jsx(ke.button,{id:m,disabled:i,"data-disabled":i?"":void 0,"data-state":Ld(b),"aria-expanded":b,"aria-controls":A,...s,ref:v,onPointerEnter:Re(t.onPointerEnter,()=>{C.current=!1,c.wasEscapeCloseRef.current=!1}),onPointerMove:Re(t.onPointerMove,Du(()=>{i||C.current||c.wasEscapeCloseRef.current||p.current||(u.onTriggerEnter(c.value),p.current=!0)})),onPointerLeave:Re(t.onPointerLeave,Du(()=>{i||(u.onTriggerLeave(),p.current=!1)})),onClick:Re(t.onClick,()=>{u.onItemSelect(c.value),C.current=b}),onKeyDown:Re(t.onKeyDown,S=>{const w={horizontal:"ArrowDown",vertical:u.dir==="rtl"?"ArrowLeft":"ArrowRight"}[u.orientation];b&&S.key===w&&(c.onEntryKeyDown(),S.preventDefault())})})})}),b&&g.jsxs(g.Fragment,{children:[g.jsx(M5,{"aria-hidden":!0,tabIndex:0,ref:c.focusProxyRef,onFocus:S=>{const x=c.contentRef.current,w=S.relatedTarget,D=w===d.current,T=x?.contains(w);(D||!T)&&c.onFocusProxyEnter(D?"start":"end")}}),u.viewport&&g.jsx("span",{"aria-owns":A})]})]})});JA.displayName=Ff;var U5="NavigationMenuLink",c1="navigationMenu.linkSelect",WA=y.forwardRef((t,a)=>{const{__scopeNavigationMenu:o,active:i,onSelect:s,...u}=t;return g.jsx(a3,{asChild:!0,children:g.jsx(ke.a,{"data-active":i?"":void 0,"aria-current":i?"page":void 0,...u,ref:a,onClick:Re(t.onClick,c=>{const d=c.target,v=new CustomEvent(c1,{bubbles:!0,cancelable:!0});if(d.addEventListener(c1,m=>s?.(m),{once:!0}),_u(d,v),!v.defaultPrevented&&!c.metaKey){const m=new CustomEvent(Su,{bubbles:!0,cancelable:!0});_u(d,m)}},{checkForDefaultPrevented:!1})})})});WA.displayName=U5;var Dd="NavigationMenuIndicator",P5=y.forwardRef((t,a)=>{const{forceMount:o,...i}=t,s=Qn(Dd,t.__scopeNavigationMenu),u=!!s.value;return s.indicatorTrack?Wy.createPortal(g.jsx(ln,{present:o||u,children:g.jsx(I5,{...i,ref:a})}),s.indicatorTrack):null});P5.displayName=Dd;var I5=y.forwardRef((t,a)=>{const{__scopeNavigationMenu:o,...i}=t,s=Qn(Dd,o),u=VA(o),[c,d]=y.useState(null),[v,m]=y.useState(null),A=s.orientation==="horizontal",p=!!s.value;y.useEffect(()=>{const S=u().find(x=>x.value===s.value)?.ref.current;S&&d(S)},[u,s.value]);const C=()=>{c&&m({size:A?c.offsetWidth:c.offsetHeight,offset:A?c.offsetLeft:c.offsetTop})};return zf(c,C),zf(s.indicatorTrack,C),v?g.jsx(ke.div,{"aria-hidden":!0,"data-state":p?"visible":"hidden","data-orientation":s.orientation,...i,ref:a,style:{position:"absolute",...A?{left:0,width:v.size+"px",transform:`translateX(${v.offset}px)`}:{top:0,height:v.size+"px",transform:`translateY(${v.offset}px)`},...i.style}}):null}),ri="NavigationMenuContent",e3=y.forwardRef((t,a)=>{const{forceMount:o,...i}=t,s=Qn(ri,t.__scopeNavigationMenu),u=XA(ri,t.__scopeNavigationMenu),c=yt(u.contentRef,a),d=u.value===s.value,v={value:u.value,triggerRef:u.triggerRef,focusProxyRef:u.focusProxyRef,wasEscapeCloseRef:u.wasEscapeCloseRef,onContentFocusOutside:u.onContentFocusOutside,onRootContentClose:u.onRootContentClose,...i};return s.viewport?g.jsx(H5,{forceMount:o,...v,ref:c}):g.jsx(ln,{present:o||d,children:g.jsx(t3,{"data-state":Ld(d),...v,ref:c,onPointerEnter:Re(t.onPointerEnter,s.onContentEnter),onPointerLeave:Re(t.onPointerLeave,Du(s.onContentLeave)),style:{pointerEvents:!d&&s.isRootMenu?"none":void 0,...v.style}})})});e3.displayName=ri;var H5=y.forwardRef((t,a)=>{const o=Qn(ri,t.__scopeNavigationMenu),{onViewportContentChange:i,onViewportContentRemove:s}=o;return Gn(()=>{i(t.value,{ref:a,...t})},[t,a,i]),Gn(()=>()=>s(t.value),[t.value,s]),null}),Su="navigationMenu.rootContentDismiss",t3=y.forwardRef((t,a)=>{const{__scopeNavigationMenu:o,value:i,triggerRef:s,focusProxyRef:u,wasEscapeCloseRef:c,onRootContentClose:d,onContentFocusOutside:v,...m}=t,A=Qn(ri,o),p=y.useRef(null),C=yt(p,a),b=r3(A.baseId,i),S=o3(A.baseId,i),x=VA(o),w=y.useRef(null),{onItemDismiss:D}=A;y.useEffect(()=>{const R=p.current;if(A.isRootMenu&&R){const _=()=>{D(),d(),R.contains(document.activeElement)&&s.current?.focus()};return R.addEventListener(Su,_),()=>R.removeEventListener(Su,_)}},[A.isRootMenu,t.value,s,D,d]);const T=y.useMemo(()=>{const _=x().map(re=>re.value);A.dir==="rtl"&&_.reverse();const N=_.indexOf(A.value),j=_.indexOf(A.previousValue),F=i===A.value,O=j===_.indexOf(i);if(!F&&!O)return w.current;const I=(()=>{if(N!==j){if(F&&j!==-1)return N>j?"from-end":"from-start";if(O&&N!==-1)return N>j?"to-start":"to-end"}return null})();return w.current=I,I},[A.previousValue,A.value,A.dir,x,i]);return g.jsx(n3,{asChild:!0,children:g.jsx(Tl,{id:S,"aria-labelledby":b,"data-motion":T,"data-orientation":A.orientation,...m,ref:C,disableOutsidePointerEvents:!1,onDismiss:()=>{const R=new Event(Su,{bubbles:!0,cancelable:!0});p.current?.dispatchEvent(R)},onFocusOutside:Re(t.onFocusOutside,R=>{v();const _=R.target;A.rootNavigationMenu?.contains(_)&&R.preventDefault()}),onPointerDownOutside:Re(t.onPointerDownOutside,R=>{const _=R.target,N=x().some(F=>F.ref.current?.contains(_)),j=A.isRootMenu&&A.viewport?.contains(_);(N||j||!A.isRootMenu)&&R.preventDefault()}),onKeyDown:Re(t.onKeyDown,R=>{const _=R.altKey||R.ctrlKey||R.metaKey;if(R.key==="Tab"&&!_){const j=kf(R.currentTarget),F=document.activeElement,O=j.findIndex(pe=>pe===F),re=R.shiftKey?j.slice(0,O).reverse():j.slice(O+1,j.length);Nd(re)?R.preventDefault():u.current?.focus()}}),onEscapeKeyDown:Re(t.onEscapeKeyDown,R=>{c.current=!0})})})}),Od="NavigationMenuViewport",B5=y.forwardRef((t,a)=>{const{forceMount:o,...i}=t,u=!!Qn(Od,t.__scopeNavigationMenu).value;return g.jsx(ln,{present:o||u,children:g.jsx($5,{...i,ref:a})})});B5.displayName=Od;var $5=y.forwardRef((t,a)=>{const{__scopeNavigationMenu:o,children:i,...s}=t,u=Qn(Od,o),c=yt(a,u.onViewportChange),d=F5(ri,t.__scopeNavigationMenu),[v,m]=y.useState(null),[A,p]=y.useState(null),C=v?v?.width+"px":void 0,b=v?v?.height+"px":void 0,S=!!u.value,x=S?u.value:u.previousValue;return zf(A,()=>{A&&m({width:A.offsetWidth,height:A.offsetHeight})}),g.jsx(ke.div,{"data-state":Ld(S),"data-orientation":u.orientation,...s,ref:c,style:{pointerEvents:!S&&u.isRootMenu?"none":void 0,"--radix-navigation-menu-viewport-width":C,"--radix-navigation-menu-viewport-height":b,...s.style},onPointerEnter:Re(t.onPointerEnter,u.onContentEnter),onPointerLeave:Re(t.onPointerLeave,Du(u.onContentLeave)),children:Array.from(d.items).map(([D,{ref:T,forceMount:R,..._}])=>{const N=x===D;return g.jsx(ln,{present:R||N,children:g.jsx(t3,{..._,ref:di(T,j=>{N&&j&&p(j)})})},D)})})}),V5="FocusGroup",n3=y.forwardRef((t,a)=>{const{__scopeNavigationMenu:o,...i}=t,s=Qn(V5,o);return g.jsx(Lf.Provider,{scope:o,children:g.jsx(Lf.Slot,{scope:o,children:g.jsx(ke.div,{dir:s.dir,...i,ref:a})})})}),f1=["ArrowRight","ArrowLeft","ArrowUp","ArrowDown"],q5="FocusGroupItem",a3=y.forwardRef((t,a)=>{const{__scopeNavigationMenu:o,...i}=t,s=O5(o),u=Qn(q5,o);return g.jsx(Lf.ItemSlot,{scope:o,children:g.jsx(ke.button,{...i,ref:a,onKeyDown:Re(t.onKeyDown,c=>{if(["Home","End",...f1].includes(c.key)){let v=s().map(p=>p.ref.current);if([u.dir==="rtl"?"ArrowRight":"ArrowLeft","ArrowUp","End"].includes(c.key)&&v.reverse(),f1.includes(c.key)){const p=v.indexOf(c.currentTarget);v=v.slice(p+1)}setTimeout(()=>Nd(v)),c.preventDefault()}})})})});function kf(t){const a=[],o=document.createTreeWalker(t,NodeFilter.SHOW_ELEMENT,{acceptNode:i=>{const s=i.tagName==="INPUT"&&i.type==="hidden";return i.disabled||i.hidden||s?NodeFilter.FILTER_SKIP:i.tabIndex>=0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}});for(;o.nextNode();)a.push(o.currentNode);return a}function Nd(t){const a=document.activeElement;return t.some(o=>o===a?!0:(o.focus(),document.activeElement!==a))}function G5(t){return t.forEach(a=>{a.dataset.tabindex=a.getAttribute("tabindex")||"",a.setAttribute("tabindex","-1")}),()=>{t.forEach(a=>{const o=a.dataset.tabindex;a.setAttribute("tabindex",o)})}}function zf(t,a){const o=on(a);Gn(()=>{let i=0;if(t){const s=new ResizeObserver(()=>{cancelAnimationFrame(i),i=window.requestAnimationFrame(o)});return s.observe(t),()=>{window.cancelAnimationFrame(i),s.unobserve(t)}}},[t,o])}function Ld(t){return t?"open":"closed"}function r3(t,a){return`${t}-trigger-${a}`}function o3(t,a){return`${t}-content-${a}`}function Du(t){return a=>a.pointerType==="mouse"?t(a):void 0}var Y5=qA,Q5=QA,K5=ZA,X5=JA,Z5=WA,J5=e3,W5="vocs_NavigationMenu",ew="vocs_NavigationMenu_list",tw="vocs_NavigationMenu_link",nw="vocs_NavigationMenu_item",aw="var(--vocs_NavigationMenu_chevronDownIcon)",rw="vocs_NavigationMenu_trigger vocs_NavigationMenu_link",ow="vocs_NavigationMenu_content";const i3=t=>g.jsx(Y5,{...t,className:me(t.className,W5)}),l3=t=>g.jsx(Q5,{...t,className:me(t.className,ew)}),Ku=({active:t,children:a,className:o,href:i})=>g.jsx(Z5,{asChild:!0,children:g.jsx(qn,{"data-active":t,className:me(o,tw),href:i,variant:"styleless",children:a})}),s3=t=>g.jsx(K5,{...t,className:me(t.className,nw)}),u3=({active:t,className:a,...o})=>{const{basePath:i}=Ot(),s=i;return g.jsx(X5,{...o,"data-active":t,className:me(a,rw),style:aa({[aw]:`url(${s}/.vocs/icons/chevron-down.svg)`})})},c3=t=>g.jsx(J5,{...t,className:me(t.className,ow)});var K2="vocs_Logo",iw="vocs_Logo_logoDark",lw="vocs_Logo_logoLight";function sw({className:t}){const{logoUrl:a}=Ot();return a?g.jsx(g.Fragment,{children:typeof a=="string"?g.jsx("img",{alt:"Logo",className:me(t,K2),src:a}):g.jsxs(g.Fragment,{children:[g.jsx("img",{alt:"Logo",className:me(t,K2,iw),src:a.dark}),g.jsx("img",{alt:"Logo",className:me(t,K2,lw),src:a.light})]})}):null}var uw="vocs_NavLogo_logoImage",cw="vocs_NavLogo_title";function jd(){const t=Ot();return t.logoUrl?g.jsx(sw,{className:uw}):g.jsx("div",{className:cw,children:t.title})}Uf.Curtain=fw;function Uf(){const t=Ot(),{showLogo:a,showSidebar:o}=_r();return g.jsxs("div",{className:me(y5,a&&!o&&A5),children:[g.jsx(g5,{}),a&&g.jsx("div",{className:x5,children:g.jsx("div",{className:S5,children:g.jsx(ni,{to:"/",style:{alignItems:"center",display:"flex",height:"56px",marginTop:"4px"},children:g.jsx(jd,{})})})}),g.jsx("div",{className:u1}),g.jsx("div",{className:u1,children:(t.topNav?.length||0)>0&&g.jsx("div",{className:E5,children:g.jsx(dw,{})})})]})}function fw(){return g.jsx("div",{className:b5})}function dw(){const{topNav:t}=Ot(),{pathname:a}=ft(),o=Rl({pathname:a,items:t||[]});return t?g.jsx(i3,{delayDuration:0,children:g.jsxs(l3,{children:[t.map((i,s)=>i.element?Jr(i.element):i.link?g.jsx(Ku,{active:o.includes(i.id),className:s1,href:i.link,children:i.text},s):i.items?g.jsxs(s3,{className:s1,children:[g.jsx(u3,{active:o.includes(i.id),children:i.text}),g.jsx(c3,{className:C5,children:g.jsx(hw,{items:i.items})})]},s):null),g.jsx(gd,{})]})}):null}function hw({items:t}){const{pathname:a}=ft(),o=Rl({pathname:a,items:t});return g.jsx("ul",{children:t?.map((i,s)=>g.jsx(Ku,{active:o.includes(i.id),href:i.link,children:i.text},s))})}function pw(){const t=wr(),a=Ot();return y.useMemo(()=>{const{pattern:o="",text:i="Edit page"}=a.editLink??{};let s="";return t.filePath&&(typeof o=="function"?s=o(t):s=o.replace(/:path/g,t.filePath)),{url:s,text:i}},[a.editLink,t])}function Fd(){const[t,a]=y.useState(!1);return y.useEffect(()=>{a(!0)},[]),t}var mw="vocs_Footer",vw="vocs_Footer_container",gw="vocs_Footer_editLink",yw="vocs_Footer_lastUpdated",Aw="vocs_Footer_navigation",d1="vocs_Footer_navigationIcon",Cw="vocs_Footer_navigationIcon_left",bw="vocs_Footer_navigationIcon_right",h1="vocs_Footer_navigationItem",Ew="vocs_Footer_navigationItem_left",Sw="vocs_Footer_navigationItem_right",p1="vocs_Footer_navigationText",m1="vocs_Footer_navigationTextInner",Pf="var(--vocs_Icon_size)",xw="vocs_Icon";function un({className:t,label:a,icon:o,size:i,style:s}){return g.jsx("div",{"aria-label":a,className:me(xw,t),role:"img",style:{...s,...aa({[Pf]:i})},children:g.jsx(o,{height:i,width:i})})}function ww(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 72 60",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"Arrow Left"}),g.jsx("path",{d:"M0.325684 29.7461C0.325684 30.8203 0.813963 31.8457 1.69286 32.6758L26.8882 57.8223C27.7671 58.6524 28.7437 59.043 29.7691 59.043C31.9175 59.043 33.5777 57.4317 33.5777 55.2344C33.5777 54.209 33.2359 53.1836 32.5035 52.5L25.7652 45.5176L9.26126 30.6738L8.38236 32.7734L21.3706 33.7012H67.4644C69.7593 33.7012 71.3706 32.041 71.3706 29.7461C71.3706 27.4512 69.7593 25.791 67.4644 25.791H21.3706L8.38236 26.7188L9.26126 28.8672L25.7652 13.9746L32.5035 6.99221C33.2359 6.30861 33.5777 5.28322 33.5777 4.25782C33.5777 2.06052 31.9175 0.449219 29.7691 0.449219C28.7437 0.449219 27.7671 0.839814 26.8882 1.66991L1.69286 26.8164C0.813963 27.6465 0.325684 28.6719 0.325684 29.7461Z",fill:"currentColor"})]})}function _w(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 72 60",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"Arrow Right"}),g.jsx("path",{d:"M71.3706 29.7461C71.3706 28.6719 70.8824 27.6465 70.0035 26.8164L44.8081 1.66991C43.9292 0.839814 42.9527 0.449219 41.9273 0.449219C39.7789 0.449219 38.1187 2.06052 38.1187 4.25782C38.1187 5.28322 38.4605 6.30861 39.1929 6.99221L45.9312 13.9746L62.4351 28.8672L63.314 26.7188L50.3257 25.791H4.23196C1.93706 25.791 0.325684 27.4512 0.325684 29.7461C0.325684 32.041 1.93706 33.7012 4.23196 33.7012H50.3257L63.314 32.7734L62.4351 30.6738L45.9312 45.5176L39.1929 52.5C38.4605 53.1836 38.1187 54.209 38.1187 55.2344C38.1187 57.4317 39.7789 59.043 41.9273 59.043C42.9527 59.043 43.9292 58.6524 44.8081 57.8223L70.0035 32.6758C70.8824 31.8457 71.3706 30.8203 71.3706 29.7461Z",fill:"currentColor"})]})}function Rw(){return g.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"Bluesky"}),g.jsx("path",{d:"M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565C.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479c.815 2.736 3.713 3.66 6.383 3.364q.204-.03.415-.056q-.207.033-.415.056c-3.912.58-7.387 2.005-2.83 7.078c5.013 5.19 6.87-1.113 7.823-4.308c.953 3.195 2.05 9.271 7.733 4.308c4.267-4.308 1.172-6.498-2.74-7.078a9 9 0 0 1-.415-.056q.21.026.415.056c2.67.297 5.568-.628 6.383-3.364c.246-.828.624-5.79.624-6.478c0-.69-.139-1.861-.902-2.206c-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8",fill:"currentColor"})]})}function Tw(){return g.jsxs("svg",{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 127.14 96.36",children:[g.jsx("title",{children:"Discord"}),g.jsx("g",{children:g.jsx("g",{children:g.jsx("g",{children:g.jsx("path",{d:"M107.7,8.07A105.15,105.15,0,0,0,81.47,0a72.06,72.06,0,0,0-3.36,6.83A97.68,97.68,0,0,0,49,6.83,72.37,72.37,0,0,0,45.64,0,105.89,105.89,0,0,0,19.39,8.09C2.79,32.65-1.71,56.6.54,80.21h0A105.73,105.73,0,0,0,32.71,96.36,77.7,77.7,0,0,0,39.6,85.25a68.42,68.42,0,0,1-10.85-5.18c.91-.66,1.8-1.34,2.66-2a75.57,75.57,0,0,0,64.32,0c.87.71,1.76,1.39,2.66,2a68.68,68.68,0,0,1-10.87,5.19,77,77,0,0,0,6.89,11.1A105.25,105.25,0,0,0,126.6,80.22h0C129.24,52.84,122.09,29.11,107.7,8.07ZM42.45,65.69C36.18,65.69,31,60,31,53s5-12.74,11.43-12.74S54,46,53.89,53,48.84,65.69,42.45,65.69Zm42.24,0C78.41,65.69,73.25,60,73.25,53s5-12.74,11.44-12.74S96.23,46,96.12,53,91.08,65.69,84.69,65.69Z",fill:"currentColor"})})})})]})}function Mw(){return g.jsxs("svg",{width:"32",height:"32",viewBox:"0 0 32 32",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"Farcaster"}),g.jsx("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M26.4552 5.28276H31.8621L31.0897 9.53103H29.738V25.7517L29.7976 25.7532C30.4097 25.7842 30.8966 26.2905 30.8966 26.9103V27.8759L30.9562 27.8774C31.5683 27.9083 32.0552 28.4146 32.0552 29.0345V30H21.2414V29.0345C21.2414 28.4146 21.7281 27.9083 22.3404 27.8774L22.4 27.8759V26.9103C22.4 26.2905 22.8868 25.7842 23.4991 25.7532L23.5587 25.7517V17.8345C23.5587 13.6752 20.1869 10.3034 16.0276 10.3034C11.8684 10.3034 8.49655 13.6752 8.49655 17.8345V25.7517L8.55614 25.7532C9.16834 25.7842 9.65517 26.2905 9.65517 26.9103V27.8759L9.71476 27.8774C10.327 27.9083 10.8138 28.4146 10.8138 29.0345V30H0V29.0345C0 28.4146 0.486832 27.9083 1.09903 27.8774L1.15862 27.8759V26.9103C1.15862 26.2905 1.64545 25.7842 2.25765 25.7532L2.31724 25.7517V9.53103H0.965517L0.193103 5.28276H5.6V2H26.4552V5.28276Z",fill:"currentColor"})]})}function Dw(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 98 96",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"GitHub"}),g.jsx("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z",fill:"currentColor"})]})}function Ow(){return g.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"100%",height:"100%",viewBox:"0 0 50 50",children:[g.jsx("title",{children:"Telegram"}),g.jsx("path",{d:"M25 2c12.703 0 23 10.297 23 23S37.703 48 25 48 2 37.703 2 25 12.297 2 25 2zm7.934 32.375c.423-1.298 2.405-14.234 2.65-16.783.074-.772-.17-1.285-.648-1.514-.578-.278-1.434-.139-2.427.219-1.362.491-18.774 7.884-19.78 8.312-.954.405-1.856.847-1.856 1.487 0 .45.267.703 1.003.966.766.273 2.695.858 3.834 1.172 1.097.303 2.346.04 3.046-.395.742-.461 9.305-6.191 9.92-6.693.614-.502 1.104.141.602.644-.502.502-6.38 6.207-7.155 6.997-.941.959-.273 1.953.358 2.351.721.454 5.906 3.932 6.687 4.49.781.558 1.573.811 2.298.811.725 0 1.107-.955 1.468-2.064z",fill:"currentColor"})]})}function Nw(){return g.jsxs("svg",{width:"32",height:"32",viewBox:"0 0 32 32",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"Warpcast"}),g.jsx("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M7.92028 31.9901H24.0698C28.4371 31.9901 31.9901 28.4373 31.9901 24.0699V7.92053C31.9901 3.55319 28.4371 0.000137329 24.0698 0.000137329H7.92028C3.55304 0.000137329 0 3.55319 0 7.92053V24.0699C0 28.4373 3.55304 31.9901 7.92028 31.9901ZM19.4134 16.048L20.9908 10.124H25.1383L21.2924 23.2218H17.7062L15.9951 17.1397L14.284 23.2218H10.7055L6.85115 10.124H10.999L12.5915 16.0916L14.1891 10.124H17.8309L19.4134 16.048Z",fill:"currentColor"})]})}function Lw(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 1200 1227",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"X"}),g.jsx("path",{d:"M714.163 519.284L1160.89 0H1055.03L667.137 450.887L357.328 0H0L468.492 681.821L0 1226.37H105.866L515.491 750.218L842.672 1226.37H1200L714.137 519.284H714.163ZM569.165 687.828L521.697 619.934L144.011 79.6944H306.615L611.412 515.685L658.88 583.579L1055.08 1150.3H892.476L569.165 687.854V687.828Z",fill:"currentColor"})]})}var jw="vocs_Socials",Fw="vocs_Socials_button",kw="vocs_Socials_icon";const zw={bluesky:Rw,discord:Tw,farcaster:Mw,github:Dw,telegram:Ow,warpcast:Nw,x:Lw},Uw={bluesky:"17px",discord:"18px",farcaster:"18px",github:"17px",telegram:"17px",warpcast:"17px",x:"16px"};function kd(){const t=Ot();return!t.socials||t.socials.length===0?null:g.jsx("div",{className:jw,children:t.socials.map((a,o)=>g.jsxs(y.Fragment,{children:[o!==0&&g.jsx("div",{style:{width:"1px",marginTop:ml[4],marginBottom:ml[4],backgroundColor:_f.border}}),g.jsx("a",{className:Fw,href:a.link,target:"_blank",rel:"noopener noreferrer",children:g.jsx(un,{className:kw,label:a.label,icon:zw[a.icon],size:Uw[a.icon]||"20px"})})]},o))})}function Pw(){const{layout:t}=_r(),a=Fd(),o=wr(),i=y.useMemo(()=>o.lastUpdatedAt?new Date(o.lastUpdatedAt):void 0,[o.lastUpdatedAt]),s=y.useMemo(()=>i?.toISOString(),[i]);return g.jsxs("footer",{className:mw,"data-layout":t,children:[t==="docs"&&g.jsxs(g.Fragment,{children:[g.jsxs("div",{className:vw,children:[g.jsx(Iw,{}),a&&o.lastUpdatedAt&&g.jsxs("div",{className:yw,children:["Last updated:"," ",g.jsx("time",{dateTime:s,children:new Intl.DateTimeFormat(void 0,{dateStyle:"short",timeStyle:"short"}).format(i)})]})]}),g.jsx(Hw,{})]}),t!=="docs"&&g.jsx(kd,{}),g.jsx(P8,{})]})}function Iw(){const t=pw();return t.url?g.jsx("div",{children:g.jsxs(qn,{className:gw,href:t.url,children:[g.jsx(F8,{})," ",t.text]})}):null}function Hw(){const t=Fd(),a=$u(),{pathname:o}=ft(),i=y.useMemo(()=>f3(a.items||[]).filter(v=>v.link),[a]),s=y.useMemo(()=>i.findIndex(v=>v.link===o),[i,o]),[u,c]=y.useMemo(()=>s<0?[]:s===0?[null,i[s+1]]:s===i.length-1?[i[s-1],null]:[i[s-1],i[s+1]],[s,i]),d=ld();return y.useEffect(()=>{let v=s,m=!1;const A=C=>{if(C.code==="ShiftLeft"&&(m=!0),m){const b=i[v+1],S=i[v-1];C.code==="ArrowRight"&&b?.link&&(!b.link.match(/^(\.*\/|#)/)?window.open(b.link,"noopener,noreferrer"):d(b.link),v++),C.code==="ArrowLeft"&&S?.link&&(!S.link.match(/^(\.*\/|#)/)?window.open(S.link,"noopener,noreferrer"):d(S.link),v--)}},p=C=>{C.code==="ShiftLeft"&&(m=!1)};return window.addEventListener("keydown",A),window.addEventListener("keyup",p),()=>{window.removeEventListener("keydown",A),window.removeEventListener("keyup",p)}},[]),t?g.jsxs("div",{className:Aw,children:[u?g.jsxs(qn,{className:me(h1,Ew),href:u.link,variant:"styleless",children:[g.jsxs("div",{className:p1,children:[g.jsx("div",{className:me(d1,Cw),style:aa({[Pf]:"0.75em"}),children:g.jsx(un,{label:"Previous",icon:ww})}),g.jsx("div",{className:m1,children:u.text})]}),g.jsx(Zo,{description:"Previous",keys:["shift","←"]})]}):g.jsx("div",{}),c?g.jsxs(qn,{className:me(h1,Sw),href:c.link,variant:"styleless",children:[g.jsxs("div",{className:p1,children:[g.jsx("div",{className:m1,style:{textAlign:"right"},children:c.text}),g.jsx("div",{className:me(d1,bw),style:aa({[Pf]:"0.75em"}),children:g.jsx(un,{label:"Next",icon:_w})})]}),g.jsx(Zo,{description:"Next",keys:["shift","→"]})]}):g.jsx("div",{})]}):null}function f3(t){const a=[];for(const o of t)o.link&&a.push(o),o.items&&a.push(...f3(o.items));return a}var Xu="Collapsible",[Bw,d3]=ra(Xu),[$w,zd]=Bw(Xu),h3=y.forwardRef((t,a)=>{const{__scopeCollapsible:o,open:i,defaultOpen:s,disabled:u,onOpenChange:c,...d}=t,[v,m]=Ca({prop:i,defaultProp:s??!1,onChange:c,caller:Xu});return g.jsx($w,{scope:o,disabled:u,contentId:$n(),open:v,onOpenToggle:y.useCallback(()=>m(A=>!A),[m]),children:g.jsx(ke.div,{"data-state":Pd(v),"data-disabled":u?"":void 0,...d,ref:a})})});h3.displayName=Xu;var p3="CollapsibleTrigger",m3=y.forwardRef((t,a)=>{const{__scopeCollapsible:o,...i}=t,s=zd(p3,o);return g.jsx(ke.button,{type:"button","aria-controls":s.contentId,"aria-expanded":s.open||!1,"data-state":Pd(s.open),"data-disabled":s.disabled?"":void 0,disabled:s.disabled,...i,ref:a,onClick:Re(t.onClick,s.onOpenToggle)})});m3.displayName=p3;var Ud="CollapsibleContent",v3=y.forwardRef((t,a)=>{const{forceMount:o,...i}=t,s=zd(Ud,t.__scopeCollapsible);return g.jsx(ln,{present:o||s.open,children:({present:u})=>g.jsx(Vw,{...i,ref:a,present:u})})});v3.displayName=Ud;var Vw=y.forwardRef((t,a)=>{const{__scopeCollapsible:o,present:i,children:s,...u}=t,c=zd(Ud,o),[d,v]=y.useState(i),m=y.useRef(null),A=yt(a,m),p=y.useRef(0),C=p.current,b=y.useRef(0),S=b.current,x=c.open||d,w=y.useRef(x),D=y.useRef(void 0);return y.useEffect(()=>{const T=requestAnimationFrame(()=>w.current=!1);return()=>cancelAnimationFrame(T)},[]),Gn(()=>{const T=m.current;if(T){D.current=D.current||{transitionDuration:T.style.transitionDuration,animationName:T.style.animationName},T.style.transitionDuration="0s",T.style.animationName="none";const R=T.getBoundingClientRect();p.current=R.height,b.current=R.width,w.current||(T.style.transitionDuration=D.current.transitionDuration,T.style.animationName=D.current.animationName),v(i)}},[c.open,i]),g.jsx(ke.div,{"data-state":Pd(c.open),"data-disabled":c.disabled?"":void 0,id:c.contentId,hidden:!x,...u,ref:A,style:{"--radix-collapsible-content-height":C?`${C}px`:void 0,"--radix-collapsible-content-width":S?`${S}px`:void 0,...t.style},children:x&&s})});function Pd(t){return t?"open":"closed"}var qw=h3,Gw=m3,Yw=v3,ia="Accordion",Qw=["Home","End","ArrowDown","ArrowUp","ArrowLeft","ArrowRight"],[Id,Kw,Xw]=Dl(ia),[Zu]=ra(ia,[Xw,d3]),Hd=d3(),g3=gt.forwardRef((t,a)=>{const{type:o,...i}=t,s=i,u=i;return g.jsx(Id.Provider,{scope:t.__scopeAccordion,children:o==="multiple"?g.jsx(e_,{...u,ref:a}):g.jsx(Ww,{...s,ref:a})})});g3.displayName=ia;var[y3,Zw]=Zu(ia),[A3,Jw]=Zu(ia,{collapsible:!1}),Ww=gt.forwardRef((t,a)=>{const{value:o,defaultValue:i,onValueChange:s=()=>{},collapsible:u=!1,...c}=t,[d,v]=Ca({prop:o,defaultProp:i??"",onChange:s,caller:ia});return g.jsx(y3,{scope:t.__scopeAccordion,value:gt.useMemo(()=>d?[d]:[],[d]),onItemOpen:v,onItemClose:gt.useCallback(()=>u&&v(""),[u,v]),children:g.jsx(A3,{scope:t.__scopeAccordion,collapsible:u,children:g.jsx(C3,{...c,ref:a})})})}),e_=gt.forwardRef((t,a)=>{const{value:o,defaultValue:i,onValueChange:s=()=>{},...u}=t,[c,d]=Ca({prop:o,defaultProp:i??[],onChange:s,caller:ia}),v=gt.useCallback(A=>d((p=[])=>[...p,A]),[d]),m=gt.useCallback(A=>d((p=[])=>p.filter(C=>C!==A)),[d]);return g.jsx(y3,{scope:t.__scopeAccordion,value:c,onItemOpen:v,onItemClose:m,children:g.jsx(A3,{scope:t.__scopeAccordion,collapsible:!0,children:g.jsx(C3,{...u,ref:a})})})}),[t_,Ju]=Zu(ia),C3=gt.forwardRef((t,a)=>{const{__scopeAccordion:o,disabled:i,dir:s,orientation:u="vertical",...c}=t,d=gt.useRef(null),v=yt(d,a),m=Kw(o),p=Ml(s)==="ltr",C=Re(t.onKeyDown,b=>{if(!Qw.includes(b.key))return;const S=b.target,x=m().filter(O=>!O.ref.current?.disabled),w=x.findIndex(O=>O.ref.current===S),D=x.length;if(w===-1)return;b.preventDefault();let T=w;const R=0,_=D-1,N=()=>{T=w+1,T>_&&(T=R)},j=()=>{T=w-1,T<R&&(T=_)};switch(b.key){case"Home":T=R;break;case"End":T=_;break;case"ArrowRight":u==="horizontal"&&(p?N():j());break;case"ArrowDown":u==="vertical"&&N();break;case"ArrowLeft":u==="horizontal"&&(p?j():N());break;case"ArrowUp":u==="vertical"&&j();break}const F=T%D;x[F].ref.current?.focus()});return g.jsx(t_,{scope:o,disabled:i,direction:s,orientation:u,children:g.jsx(Id.Slot,{scope:o,children:g.jsx(ke.div,{...c,"data-orientation":u,ref:v,onKeyDown:i?void 0:C})})})}),Ou="AccordionItem",[n_,Bd]=Zu(Ou),b3=gt.forwardRef((t,a)=>{const{__scopeAccordion:o,value:i,...s}=t,u=Ju(Ou,o),c=Zw(Ou,o),d=Hd(o),v=$n(),m=i&&c.value.includes(i)||!1,A=u.disabled||t.disabled;return g.jsx(n_,{scope:o,open:m,disabled:A,triggerId:v,children:g.jsx(qw,{"data-orientation":u.orientation,"data-state":_3(m),...d,...s,ref:a,disabled:A,open:m,onOpenChange:p=>{p?c.onItemOpen(i):c.onItemClose(i)}})})});b3.displayName=Ou;var E3="AccordionHeader",a_=gt.forwardRef((t,a)=>{const{__scopeAccordion:o,...i}=t,s=Ju(ia,o),u=Bd(E3,o);return g.jsx(ke.h3,{"data-orientation":s.orientation,"data-state":_3(u.open),"data-disabled":u.disabled?"":void 0,...i,ref:a})});a_.displayName=E3;var If="AccordionTrigger",S3=gt.forwardRef((t,a)=>{const{__scopeAccordion:o,...i}=t,s=Ju(ia,o),u=Bd(If,o),c=Jw(If,o),d=Hd(o);return g.jsx(Id.ItemSlot,{scope:o,children:g.jsx(Gw,{"aria-disabled":u.open&&!c.collapsible||void 0,"data-orientation":s.orientation,id:u.triggerId,...d,...i,ref:a})})});S3.displayName=If;var x3="AccordionContent",w3=gt.forwardRef((t,a)=>{const{__scopeAccordion:o,...i}=t,s=Ju(ia,o),u=Bd(x3,o),c=Hd(o);return g.jsx(Yw,{role:"region","aria-labelledby":u.triggerId,"data-orientation":s.orientation,...c,...i,ref:a,style:{"--radix-accordion-content-height":"var(--radix-collapsible-content-height)","--radix-accordion-content-width":"var(--radix-collapsible-content-width)",...t.style}})});w3.displayName=x3;function _3(t){return t?"open":"closed"}var r_=g3,o_=b3,i_=S3,l_=w3;function R3(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"Chevron Down"}),g.jsx("path",{d:"M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z",fill:"currentColor",fillRule:"evenodd",clipRule:"evenodd"})]})}function T3(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"Chevron Right"}),g.jsx("path",{d:"M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z",fill:"currentColor",fillRule:"evenodd",clipRule:"evenodd"})]})}function s_(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"Chevron Up"}),g.jsx("path",{d:"M3.13523 8.84197C3.3241 9.04343 3.64052 9.05363 3.84197 8.86477L7.5 5.43536L11.158 8.86477C11.3595 9.05363 11.6759 9.04343 11.8648 8.84197C12.0536 8.64051 12.0434 8.32409 11.842 8.13523L7.84197 4.38523C7.64964 4.20492 7.35036 4.20492 7.15803 4.38523L3.15803 8.13523C2.95657 8.32409 2.94637 8.64051 3.13523 8.84197Z",fill:"currentColor",fillRule:"evenodd",clipRule:"evenodd"})]})}function M3(){return g.jsxs("svg",{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 79 48",fill:"none",children:[g.jsx("title",{children:"Menu"}),g.jsx("path",{fill:"currentColor",d:"M19.528 47.232h40.87c1.952 0 3.515-1.562 3.515-3.564a3.5 3.5 0 0 0-3.516-3.516H19.528a3.501 3.501 0 0 0-3.515 3.516c0 2.002 1.562 3.564 3.515 3.564ZM12.057 27.262h55.81a3.501 3.501 0 0 0 3.516-3.516 3.501 3.501 0 0 0-3.515-3.515h-55.81a3.501 3.501 0 0 0-3.516 3.515 3.501 3.501 0 0 0 3.515 3.516ZM4.391 7.34H75.29c2.002 0 3.515-1.563 3.515-3.516 0-2.002-1.513-3.564-3.515-3.564H4.39C2.438.26.876 1.822.876 3.824A3.501 3.501 0 0 0 4.39 7.34Z"})]})}var u_="vocs_MobileSearch_searchButton";function c_(){const[t]=wd("q",{defaultValue:""}),[a,o]=y.useState(!1),i=TA("(max-width: 1080px)");return y.useEffect(()=>{i&&t&&o(!0)},[i,t]),g.jsxs(wA,{open:a,onOpenChange:o,children:[g.jsx(_A,{asChild:!0,children:g.jsx("button",{className:u_,type:"button","aria-label":"Search",children:g.jsx(vd,{height:21,width:21})})}),i&&g.jsx(BA,{open:a,onClose:()=>o(!1)})]})}var f_="vocs_MobileTopNav",d_="vocs_MobileTopNav_content",h_="vocs_MobileTopNav_curtain",v1="vocs_MobileTopNav_curtainGroup",X2="vocs_MobileTopNav_curtainItem",Z2="vocs_MobileTopNav_group",p_="vocs_MobileTopNav_item",m_="vocs_MobileTopNav_logo",D3="vocs_MobileTopNav_menuTrigger",v_="vocs_MobileTopNav_menuTitle",g_="vocs_MobileTopNav_navigation_compact",O3="vocs_MobileTopNav_navigation",y_="vocs_MobileTopNav_navigationContent",fu="vocs_MobileTopNav_navigationItem",A_="var(--vocs_MobileTopNav_chevronDownIcon)",C_="var(--vocs_MobileTopNav_chevronUpIcon)",b_="vocs_MobileTopNav_trigger",g1="vocs_MobileTopNav_outlineTrigger",E_="vocs_MobileTopNav_outlinePopover",y1="vocs_MobileTopNav_section",S_="vocs_MobileTopNav_separator",x_="vocs_MobileTopNav_sidebarPopover",w_="vocs_MobileTopNav_topNavPopover",__="vocs_MobileTopNav_topNavPopoverFooter";function R_(t,a){let o=!1;return()=>{o=!0,setTimeout(()=>{o&&t(),o=!1},a)}}function T_(t){const[a,o]=y.useState(void 0);return Gn(()=>{if(t){o({width:t.offsetWidth,height:t.offsetHeight});const i=new ResizeObserver(s=>{if(!Array.isArray(s)||!s.length)return;const u=s[0];let c,d;if("borderBoxSize"in u){const v=u.borderBoxSize,m=Array.isArray(v)?v[0]:v;c=m.inlineSize,d=m.blockSize}else c=t.offsetWidth,d=t.offsetHeight;o({width:c,height:d})});return i.observe(t,{box:"border-box"}),()=>i.unobserve(t)}else o(void 0)},[t]),a}const M_=["top","right","bottom","left"],Sr=Math.min,Tn=Math.max,Nu=Math.round,du=Math.floor,ga=t=>({x:t,y:t}),D_={left:"right",right:"left",bottom:"top",top:"bottom"};function Hf(t,a,o){return Tn(t,Sr(a,o))}function Ba(t,a){return typeof t=="function"?t(a):t}function $a(t){return t.split("-")[0]}function hi(t){return t.split("-")[1]}function $d(t){return t==="x"?"y":"x"}function Vd(t){return t==="y"?"height":"width"}function va(t){const a=t[0];return a==="t"||a==="b"?"y":"x"}function qd(t){return $d(va(t))}function O_(t,a,o){o===void 0&&(o=!1);const i=hi(t),s=qd(t),u=Vd(s);let c=s==="x"?i===(o?"end":"start")?"right":"left":i==="start"?"bottom":"top";return a.reference[u]>a.floating[u]&&(c=Lu(c)),[c,Lu(c)]}function N_(t){const a=Lu(t);return[Bf(t),a,Bf(a)]}function Bf(t){return t.includes("start")?t.replace("start","end"):t.replace("end","start")}const A1=["left","right"],C1=["right","left"],L_=["top","bottom"],j_=["bottom","top"];function F_(t,a,o){switch(t){case"top":case"bottom":return o?a?C1:A1:a?A1:C1;case"left":case"right":return a?L_:j_;default:return[]}}function k_(t,a,o,i){const s=hi(t);let u=F_($a(t),o==="start",i);return s&&(u=u.map(c=>c+"-"+s),a&&(u=u.concat(u.map(Bf)))),u}function Lu(t){const a=$a(t);return D_[a]+t.slice(a.length)}function z_(t){return{top:0,right:0,bottom:0,left:0,...t}}function N3(t){return typeof t!="number"?z_(t):{top:t,right:t,bottom:t,left:t}}function ju(t){const{x:a,y:o,width:i,height:s}=t;return{width:i,height:s,top:o,left:a,right:a+i,bottom:o+s,x:a,y:o}}function b1(t,a,o){let{reference:i,floating:s}=t;const u=va(a),c=qd(a),d=Vd(c),v=$a(a),m=u==="y",A=i.x+i.width/2-s.width/2,p=i.y+i.height/2-s.height/2,C=i[d]/2-s[d]/2;let b;switch(v){case"top":b={x:A,y:i.y-s.height};break;case"bottom":b={x:A,y:i.y+i.height};break;case"right":b={x:i.x+i.width,y:p};break;case"left":b={x:i.x-s.width,y:p};break;default:b={x:i.x,y:i.y}}switch(hi(a)){case"start":b[c]-=C*(o&&m?-1:1);break;case"end":b[c]+=C*(o&&m?-1:1);break}return b}async function U_(t,a){var o;a===void 0&&(a={});const{x:i,y:s,platform:u,rects:c,elements:d,strategy:v}=t,{boundary:m="clippingAncestors",rootBoundary:A="viewport",elementContext:p="floating",altBoundary:C=!1,padding:b=0}=Ba(a,t),S=N3(b),w=d[C?p==="floating"?"reference":"floating":p],D=ju(await u.getClippingRect({element:(o=await(u.isElement==null?void 0:u.isElement(w)))==null||o?w:w.contextElement||await(u.getDocumentElement==null?void 0:u.getDocumentElement(d.floating)),boundary:m,rootBoundary:A,strategy:v})),T=p==="floating"?{x:i,y:s,width:c.floating.width,height:c.floating.height}:c.reference,R=await(u.getOffsetParent==null?void 0:u.getOffsetParent(d.floating)),_=await(u.isElement==null?void 0:u.isElement(R))?await(u.getScale==null?void 0:u.getScale(R))||{x:1,y:1}:{x:1,y:1},N=ju(u.convertOffsetParentRelativeRectToViewportRelativeRect?await u.convertOffsetParentRelativeRectToViewportRelativeRect({elements:d,rect:T,offsetParent:R,strategy:v}):T);return{top:(D.top-N.top+S.top)/_.y,bottom:(N.bottom-D.bottom+S.bottom)/_.y,left:(D.left-N.left+S.left)/_.x,right:(N.right-D.right+S.right)/_.x}}const P_=50,I_=async(t,a,o)=>{const{placement:i="bottom",strategy:s="absolute",middleware:u=[],platform:c}=o,d=c.detectOverflow?c:{...c,detectOverflow:U_},v=await(c.isRTL==null?void 0:c.isRTL(a));let m=await c.getElementRects({reference:t,floating:a,strategy:s}),{x:A,y:p}=b1(m,i,v),C=i,b=0;const S={};for(let x=0;x<u.length;x++){const w=u[x];if(!w)continue;const{name:D,fn:T}=w,{x:R,y:_,data:N,reset:j}=await T({x:A,y:p,initialPlacement:i,placement:C,strategy:s,middlewareData:S,rects:m,platform:d,elements:{reference:t,floating:a}});A=R??A,p=_??p,S[D]={...S[D],...N},j&&b<P_&&(b++,typeof j=="object"&&(j.placement&&(C=j.placement),j.rects&&(m=j.rects===!0?await c.getElementRects({reference:t,floating:a,strategy:s}):j.rects),{x:A,y:p}=b1(m,C,v)),x=-1)}return{x:A,y:p,placement:C,strategy:s,middlewareData:S}},H_=t=>({name:"arrow",options:t,async fn(a){const{x:o,y:i,placement:s,rects:u,platform:c,elements:d,middlewareData:v}=a,{element:m,padding:A=0}=Ba(t,a)||{};if(m==null)return{};const p=N3(A),C={x:o,y:i},b=qd(s),S=Vd(b),x=await c.getDimensions(m),w=b==="y",D=w?"top":"left",T=w?"bottom":"right",R=w?"clientHeight":"clientWidth",_=u.reference[S]+u.reference[b]-C[b]-u.floating[S],N=C[b]-u.reference[b],j=await(c.getOffsetParent==null?void 0:c.getOffsetParent(m));let F=j?j[R]:0;(!F||!await(c.isElement==null?void 0:c.isElement(j)))&&(F=d.floating[R]||u.floating[S]);const O=_/2-N/2,I=F/2-x[S]/2-1,re=Sr(p[D],I),pe=Sr(p[T],I),ce=re,de=F-x[S]-pe,J=F/2-x[S]/2+O,fe=Hf(ce,J,de),U=!v.arrow&&hi(s)!=null&&J!==fe&&u.reference[S]/2-(J<ce?re:pe)-x[S]/2<0,H=U?J<ce?J-ce:J-de:0;return{[b]:C[b]+H,data:{[b]:fe,centerOffset:J-fe-H,...U&&{alignmentOffset:H}},reset:U}}}),B_=function(t){return t===void 0&&(t={}),{name:"flip",options:t,async fn(a){var o,i;const{placement:s,middlewareData:u,rects:c,initialPlacement:d,platform:v,elements:m}=a,{mainAxis:A=!0,crossAxis:p=!0,fallbackPlacements:C,fallbackStrategy:b="bestFit",fallbackAxisSideDirection:S="none",flipAlignment:x=!0,...w}=Ba(t,a);if((o=u.arrow)!=null&&o.alignmentOffset)return{};const D=$a(s),T=va(d),R=$a(d)===d,_=await(v.isRTL==null?void 0:v.isRTL(m.floating)),N=C||(R||!x?[Lu(d)]:N_(d)),j=S!=="none";!C&&j&&N.push(...k_(d,x,S,_));const F=[d,...N],O=await v.detectOverflow(a,w),I=[];let re=((i=u.flip)==null?void 0:i.overflows)||[];if(A&&I.push(O[D]),p){const J=O_(s,c,_);I.push(O[J[0]],O[J[1]])}if(re=[...re,{placement:s,overflows:I}],!I.every(J=>J<=0)){var pe,ce;const J=(((pe=u.flip)==null?void 0:pe.index)||0)+1,fe=F[J];if(fe&&(!(p==="alignment"?T!==va(fe):!1)||re.every(K=>va(K.placement)===T?K.overflows[0]>0:!0)))return{data:{index:J,overflows:re},reset:{placement:fe}};let U=(ce=re.filter(H=>H.overflows[0]<=0).sort((H,K)=>H.overflows[1]-K.overflows[1])[0])==null?void 0:ce.placement;if(!U)switch(b){case"bestFit":{var de;const H=(de=re.filter(K=>{if(j){const G=va(K.placement);return G===T||G==="y"}return!0}).map(K=>[K.placement,K.overflows.filter(G=>G>0).reduce((G,se)=>G+se,0)]).sort((K,G)=>K[1]-G[1])[0])==null?void 0:de[0];H&&(U=H);break}case"initialPlacement":U=d;break}if(s!==U)return{reset:{placement:U}}}return{}}}};function E1(t,a){return{top:t.top-a.height,right:t.right-a.width,bottom:t.bottom-a.height,left:t.left-a.width}}function S1(t){return M_.some(a=>t[a]>=0)}const $_=function(t){return t===void 0&&(t={}),{name:"hide",options:t,async fn(a){const{rects:o,platform:i}=a,{strategy:s="referenceHidden",...u}=Ba(t,a);switch(s){case"referenceHidden":{const c=await i.detectOverflow(a,{...u,elementContext:"reference"}),d=E1(c,o.reference);return{data:{referenceHiddenOffsets:d,referenceHidden:S1(d)}}}case"escaped":{const c=await i.detectOverflow(a,{...u,altBoundary:!0}),d=E1(c,o.floating);return{data:{escapedOffsets:d,escaped:S1(d)}}}default:return{}}}}},L3=new Set(["left","top"]);async function V_(t,a){const{placement:o,platform:i,elements:s}=t,u=await(i.isRTL==null?void 0:i.isRTL(s.floating)),c=$a(o),d=hi(o),v=va(o)==="y",m=L3.has(c)?-1:1,A=u&&v?-1:1,p=Ba(a,t);let{mainAxis:C,crossAxis:b,alignmentAxis:S}=typeof p=="number"?{mainAxis:p,crossAxis:0,alignmentAxis:null}:{mainAxis:p.mainAxis||0,crossAxis:p.crossAxis||0,alignmentAxis:p.alignmentAxis};return d&&typeof S=="number"&&(b=d==="end"?S*-1:S),v?{x:b*A,y:C*m}:{x:C*m,y:b*A}}const q_=function(t){return t===void 0&&(t=0),{name:"offset",options:t,async fn(a){var o,i;const{x:s,y:u,placement:c,middlewareData:d}=a,v=await V_(a,t);return c===((o=d.offset)==null?void 0:o.placement)&&(i=d.arrow)!=null&&i.alignmentOffset?{}:{x:s+v.x,y:u+v.y,data:{...v,placement:c}}}}},G_=function(t){return t===void 0&&(t={}),{name:"shift",options:t,async fn(a){const{x:o,y:i,placement:s,platform:u}=a,{mainAxis:c=!0,crossAxis:d=!1,limiter:v={fn:D=>{let{x:T,y:R}=D;return{x:T,y:R}}},...m}=Ba(t,a),A={x:o,y:i},p=await u.detectOverflow(a,m),C=va($a(s)),b=$d(C);let S=A[b],x=A[C];if(c){const D=b==="y"?"top":"left",T=b==="y"?"bottom":"right",R=S+p[D],_=S-p[T];S=Hf(R,S,_)}if(d){const D=C==="y"?"top":"left",T=C==="y"?"bottom":"right",R=x+p[D],_=x-p[T];x=Hf(R,x,_)}const w=v.fn({...a,[b]:S,[C]:x});return{...w,data:{x:w.x-o,y:w.y-i,enabled:{[b]:c,[C]:d}}}}}},Y_=function(t){return t===void 0&&(t={}),{options:t,fn(a){const{x:o,y:i,placement:s,rects:u,middlewareData:c}=a,{offset:d=0,mainAxis:v=!0,crossAxis:m=!0}=Ba(t,a),A={x:o,y:i},p=va(s),C=$d(p);let b=A[C],S=A[p];const x=Ba(d,a),w=typeof x=="number"?{mainAxis:x,crossAxis:0}:{mainAxis:0,crossAxis:0,...x};if(v){const R=C==="y"?"height":"width",_=u.reference[C]-u.floating[R]+w.mainAxis,N=u.reference[C]+u.reference[R]-w.mainAxis;b<_?b=_:b>N&&(b=N)}if(m){var D,T;const R=C==="y"?"width":"height",_=L3.has($a(s)),N=u.reference[p]-u.floating[R]+(_&&((D=c.offset)==null?void 0:D[p])||0)+(_?0:w.crossAxis),j=u.reference[p]+u.reference[R]+(_?0:((T=c.offset)==null?void 0:T[p])||0)-(_?w.crossAxis:0);S<N?S=N:S>j&&(S=j)}return{[C]:b,[p]:S}}}},Q_=function(t){return t===void 0&&(t={}),{name:"size",options:t,async fn(a){var o,i;const{placement:s,rects:u,platform:c,elements:d}=a,{apply:v=()=>{},...m}=Ba(t,a),A=await c.detectOverflow(a,m),p=$a(s),C=hi(s),b=va(s)==="y",{width:S,height:x}=u.floating;let w,D;p==="top"||p==="bottom"?(w=p,D=C===(await(c.isRTL==null?void 0:c.isRTL(d.floating))?"start":"end")?"left":"right"):(D=p,w=C==="end"?"top":"bottom");const T=x-A.top-A.bottom,R=S-A.left-A.right,_=Sr(x-A[w],T),N=Sr(S-A[D],R),j=!a.middlewareData.shift;let F=_,O=N;if((o=a.middlewareData.shift)!=null&&o.enabled.x&&(O=R),(i=a.middlewareData.shift)!=null&&i.enabled.y&&(F=T),j&&!C){const re=Tn(A.left,0),pe=Tn(A.right,0),ce=Tn(A.top,0),de=Tn(A.bottom,0);b?O=S-2*(re!==0||pe!==0?re+pe:Tn(A.left,A.right)):F=x-2*(ce!==0||de!==0?ce+de:Tn(A.top,A.bottom))}await v({...a,availableWidth:O,availableHeight:F});const I=await c.getDimensions(d.floating);return S!==I.width||x!==I.height?{reset:{rects:!0}}:{}}}};function Wu(){return typeof window<"u"}function pi(t){return j3(t)?(t.nodeName||"").toLowerCase():"#document"}function Mn(t){var a;return(t==null||(a=t.ownerDocument)==null?void 0:a.defaultView)||window}function ba(t){var a;return(a=(j3(t)?t.ownerDocument:t.document)||window.document)==null?void 0:a.documentElement}function j3(t){return Wu()?t instanceof Node||t instanceof Mn(t).Node:!1}function Qt(t){return Wu()?t instanceof Element||t instanceof Mn(t).Element:!1}function Ga(t){return Wu()?t instanceof HTMLElement||t instanceof Mn(t).HTMLElement:!1}function Fu(t){return!Wu()||typeof ShadowRoot>"u"?!1:t instanceof ShadowRoot||t instanceof Mn(t).ShadowRoot}function Ol(t){const{overflow:a,overflowX:o,overflowY:i,display:s}=Yn(t);return/auto|scroll|overlay|hidden|clip/.test(a+i+o)&&s!=="inline"&&s!=="contents"}function K_(t){return/^(table|td|th)$/.test(pi(t))}function ec(t){try{if(t.matches(":popover-open"))return!0}catch{}try{return t.matches(":modal")}catch{return!1}}const X_=/transform|translate|scale|rotate|perspective|filter/,Z_=/paint|layout|strict|content/,Qr=t=>!!t&&t!=="none";let J2;function Gd(t){const a=Qt(t)?Yn(t):t;return Qr(a.transform)||Qr(a.translate)||Qr(a.scale)||Qr(a.rotate)||Qr(a.perspective)||!Yd()&&(Qr(a.backdropFilter)||Qr(a.filter))||X_.test(a.willChange||"")||Z_.test(a.contain||"")}function J_(t){let a=xr(t);for(;Ga(a)&&!oi(a);){if(Gd(a))return a;if(ec(a))return null;a=xr(a)}return null}function Yd(){return J2==null&&(J2=typeof CSS<"u"&&CSS.supports&&CSS.supports("-webkit-backdrop-filter","none")),J2}function oi(t){return/^(html|body|#document)$/.test(pi(t))}function Yn(t){return Mn(t).getComputedStyle(t)}function tc(t){return Qt(t)?{scrollLeft:t.scrollLeft,scrollTop:t.scrollTop}:{scrollLeft:t.scrollX,scrollTop:t.scrollY}}function xr(t){if(pi(t)==="html")return t;const a=t.assignedSlot||t.parentNode||Fu(t)&&t.host||ba(t);return Fu(a)?a.host:a}function F3(t){const a=xr(t);return oi(a)?t.ownerDocument?t.ownerDocument.body:t.body:Ga(a)&&Ol(a)?a:F3(a)}function Al(t,a,o){var i;a===void 0&&(a=[]),o===void 0&&(o=!0);const s=F3(t),u=s===((i=t.ownerDocument)==null?void 0:i.body),c=Mn(s);if(u){const d=$f(c);return a.concat(c,c.visualViewport||[],Ol(s)?s:[],d&&o?Al(d):[])}else return a.concat(s,Al(s,[],o))}function $f(t){return t.parent&&Object.getPrototypeOf(t.parent)?t.frameElement:null}function k3(t){const a=Yn(t);let o=parseFloat(a.width)||0,i=parseFloat(a.height)||0;const s=Ga(t),u=s?t.offsetWidth:o,c=s?t.offsetHeight:i,d=Nu(o)!==u||Nu(i)!==c;return d&&(o=u,i=c),{width:o,height:i,$:d}}function Qd(t){return Qt(t)?t:t.contextElement}function ti(t){const a=Qd(t);if(!Ga(a))return ga(1);const o=a.getBoundingClientRect(),{width:i,height:s,$:u}=k3(a);let c=(u?Nu(o.width):o.width)/i,d=(u?Nu(o.height):o.height)/s;return(!c||!Number.isFinite(c))&&(c=1),(!d||!Number.isFinite(d))&&(d=1),{x:c,y:d}}const W_=ga(0);function z3(t){const a=Mn(t);return!Yd()||!a.visualViewport?W_:{x:a.visualViewport.offsetLeft,y:a.visualViewport.offsetTop}}function eR(t,a,o){return a===void 0&&(a=!1),!o||a&&o!==Mn(t)?!1:a}function eo(t,a,o,i){a===void 0&&(a=!1),o===void 0&&(o=!1);const s=t.getBoundingClientRect(),u=Qd(t);let c=ga(1);a&&(i?Qt(i)&&(c=ti(i)):c=ti(t));const d=eR(u,o,i)?z3(u):ga(0);let v=(s.left+d.x)/c.x,m=(s.top+d.y)/c.y,A=s.width/c.x,p=s.height/c.y;if(u){const C=Mn(u),b=i&&Qt(i)?Mn(i):i;let S=C,x=$f(S);for(;x&&i&&b!==S;){const w=ti(x),D=x.getBoundingClientRect(),T=Yn(x),R=D.left+(x.clientLeft+parseFloat(T.paddingLeft))*w.x,_=D.top+(x.clientTop+parseFloat(T.paddingTop))*w.y;v*=w.x,m*=w.y,A*=w.x,p*=w.y,v+=R,m+=_,S=Mn(x),x=$f(S)}}return ju({width:A,height:p,x:v,y:m})}function nc(t,a){const o=tc(t).scrollLeft;return a?a.left+o:eo(ba(t)).left+o}function U3(t,a){const o=t.getBoundingClientRect(),i=o.left+a.scrollLeft-nc(t,o),s=o.top+a.scrollTop;return{x:i,y:s}}function tR(t){let{elements:a,rect:o,offsetParent:i,strategy:s}=t;const u=s==="fixed",c=ba(i),d=a?ec(a.floating):!1;if(i===c||d&&u)return o;let v={scrollLeft:0,scrollTop:0},m=ga(1);const A=ga(0),p=Ga(i);if((p||!p&&!u)&&((pi(i)!=="body"||Ol(c))&&(v=tc(i)),p)){const b=eo(i);m=ti(i),A.x=b.x+i.clientLeft,A.y=b.y+i.clientTop}const C=c&&!p&&!u?U3(c,v):ga(0);return{width:o.width*m.x,height:o.height*m.y,x:o.x*m.x-v.scrollLeft*m.x+A.x+C.x,y:o.y*m.y-v.scrollTop*m.y+A.y+C.y}}function nR(t){return Array.from(t.getClientRects())}function aR(t){const a=ba(t),o=tc(t),i=t.ownerDocument.body,s=Tn(a.scrollWidth,a.clientWidth,i.scrollWidth,i.clientWidth),u=Tn(a.scrollHeight,a.clientHeight,i.scrollHeight,i.clientHeight);let c=-o.scrollLeft+nc(t);const d=-o.scrollTop;return Yn(i).direction==="rtl"&&(c+=Tn(a.clientWidth,i.clientWidth)-s),{width:s,height:u,x:c,y:d}}const x1=25;function rR(t,a){const o=Mn(t),i=ba(t),s=o.visualViewport;let u=i.clientWidth,c=i.clientHeight,d=0,v=0;if(s){u=s.width,c=s.height;const A=Yd();(!A||A&&a==="fixed")&&(d=s.offsetLeft,v=s.offsetTop)}const m=nc(i);if(m<=0){const A=i.ownerDocument,p=A.body,C=getComputedStyle(p),b=A.compatMode==="CSS1Compat"&&parseFloat(C.marginLeft)+parseFloat(C.marginRight)||0,S=Math.abs(i.clientWidth-p.clientWidth-b);S<=x1&&(u-=S)}else m<=x1&&(u+=m);return{width:u,height:c,x:d,y:v}}function oR(t,a){const o=eo(t,!0,a==="fixed"),i=o.top+t.clientTop,s=o.left+t.clientLeft,u=Ga(t)?ti(t):ga(1),c=t.clientWidth*u.x,d=t.clientHeight*u.y,v=s*u.x,m=i*u.y;return{width:c,height:d,x:v,y:m}}function w1(t,a,o){let i;if(a==="viewport")i=rR(t,o);else if(a==="document")i=aR(ba(t));else if(Qt(a))i=oR(a,o);else{const s=z3(t);i={x:a.x-s.x,y:a.y-s.y,width:a.width,height:a.height}}return ju(i)}function P3(t,a){const o=xr(t);return o===a||!Qt(o)||oi(o)?!1:Yn(o).position==="fixed"||P3(o,a)}function iR(t,a){const o=a.get(t);if(o)return o;let i=Al(t,[],!1).filter(d=>Qt(d)&&pi(d)!=="body"),s=null;const u=Yn(t).position==="fixed";let c=u?xr(t):t;for(;Qt(c)&&!oi(c);){const d=Yn(c),v=Gd(c);!v&&d.position==="fixed"&&(s=null),(u?!v&&!s:!v&&d.position==="static"&&!!s&&(s.position==="absolute"||s.position==="fixed")||Ol(c)&&!v&&P3(t,c))?i=i.filter(A=>A!==c):s=d,c=xr(c)}return a.set(t,i),i}function lR(t){let{element:a,boundary:o,rootBoundary:i,strategy:s}=t;const c=[...o==="clippingAncestors"?ec(a)?[]:iR(a,this._c):[].concat(o),i],d=w1(a,c[0],s);let v=d.top,m=d.right,A=d.bottom,p=d.left;for(let C=1;C<c.length;C++){const b=w1(a,c[C],s);v=Tn(b.top,v),m=Sr(b.right,m),A=Sr(b.bottom,A),p=Tn(b.left,p)}return{width:m-p,height:A-v,x:p,y:v}}function sR(t){const{width:a,height:o}=k3(t);return{width:a,height:o}}function uR(t,a,o){const i=Ga(a),s=ba(a),u=o==="fixed",c=eo(t,!0,u,a);let d={scrollLeft:0,scrollTop:0};const v=ga(0);function m(){v.x=nc(s)}if(i||!i&&!u)if((pi(a)!=="body"||Ol(s))&&(d=tc(a)),i){const b=eo(a,!0,u,a);v.x=b.x+a.clientLeft,v.y=b.y+a.clientTop}else s&&m();u&&!i&&s&&m();const A=s&&!i&&!u?U3(s,d):ga(0),p=c.left+d.scrollLeft-v.x-A.x,C=c.top+d.scrollTop-v.y-A.y;return{x:p,y:C,width:c.width,height:c.height}}function W2(t){return Yn(t).position==="static"}function _1(t,a){if(!Ga(t)||Yn(t).position==="fixed")return null;if(a)return a(t);let o=t.offsetParent;return ba(t)===o&&(o=o.ownerDocument.body),o}function I3(t,a){const o=Mn(t);if(ec(t))return o;if(!Ga(t)){let s=xr(t);for(;s&&!oi(s);){if(Qt(s)&&!W2(s))return s;s=xr(s)}return o}let i=_1(t,a);for(;i&&K_(i)&&W2(i);)i=_1(i,a);return i&&oi(i)&&W2(i)&&!Gd(i)?o:i||J_(t)||o}const cR=async function(t){const a=this.getOffsetParent||I3,o=this.getDimensions,i=await o(t.floating);return{reference:uR(t.reference,await a(t.floating),t.strategy),floating:{x:0,y:0,width:i.width,height:i.height}}};function fR(t){return Yn(t).direction==="rtl"}const dR={convertOffsetParentRelativeRectToViewportRelativeRect:tR,getDocumentElement:ba,getClippingRect:lR,getOffsetParent:I3,getElementRects:cR,getClientRects:nR,getDimensions:sR,getScale:ti,isElement:Qt,isRTL:fR};function H3(t,a){return t.x===a.x&&t.y===a.y&&t.width===a.width&&t.height===a.height}function hR(t,a){let o=null,i;const s=ba(t);function u(){var d;clearTimeout(i),(d=o)==null||d.disconnect(),o=null}function c(d,v){d===void 0&&(d=!1),v===void 0&&(v=1),u();const m=t.getBoundingClientRect(),{left:A,top:p,width:C,height:b}=m;if(d||a(),!C||!b)return;const S=du(p),x=du(s.clientWidth-(A+C)),w=du(s.clientHeight-(p+b)),D=du(A),R={rootMargin:-S+"px "+-x+"px "+-w+"px "+-D+"px",threshold:Tn(0,Sr(1,v))||1};let _=!0;function N(j){const F=j[0].intersectionRatio;if(F!==v){if(!_)return c();F?c(!1,F):i=setTimeout(()=>{c(!1,1e-7)},1e3)}F===1&&!H3(m,t.getBoundingClientRect())&&c(),_=!1}try{o=new IntersectionObserver(N,{...R,root:s.ownerDocument})}catch{o=new IntersectionObserver(N,R)}o.observe(t)}return c(!0),u}function pR(t,a,o,i){i===void 0&&(i={});const{ancestorScroll:s=!0,ancestorResize:u=!0,elementResize:c=typeof ResizeObserver=="function",layoutShift:d=typeof IntersectionObserver=="function",animationFrame:v=!1}=i,m=Qd(t),A=s||u?[...m?Al(m):[],...a?Al(a):[]]:[];A.forEach(D=>{s&&D.addEventListener("scroll",o,{passive:!0}),u&&D.addEventListener("resize",o)});const p=m&&d?hR(m,o):null;let C=-1,b=null;c&&(b=new ResizeObserver(D=>{let[T]=D;T&&T.target===m&&b&&a&&(b.unobserve(a),cancelAnimationFrame(C),C=requestAnimationFrame(()=>{var R;(R=b)==null||R.observe(a)})),o()}),m&&!v&&b.observe(m),a&&b.observe(a));let S,x=v?eo(t):null;v&&w();function w(){const D=eo(t);x&&!H3(x,D)&&o(),x=D,S=requestAnimationFrame(w)}return o(),()=>{var D;A.forEach(T=>{s&&T.removeEventListener("scroll",o),u&&T.removeEventListener("resize",o)}),p?.(),(D=b)==null||D.disconnect(),b=null,v&&cancelAnimationFrame(S)}}const mR=q_,vR=G_,gR=B_,yR=Q_,AR=$_,R1=H_,CR=Y_,bR=(t,a,o)=>{const i=new Map,s={platform:dR,...o},u={...s.platform,_c:i};return I_(t,a,{...s,platform:u})};var ER=typeof document<"u",SR=function(){},xu=ER?y.useLayoutEffect:SR;function ku(t,a){if(t===a)return!0;if(typeof t!=typeof a)return!1;if(typeof t=="function"&&t.toString()===a.toString())return!0;let o,i,s;if(t&&a&&typeof t=="object"){if(Array.isArray(t)){if(o=t.length,o!==a.length)return!1;for(i=o;i--!==0;)if(!ku(t[i],a[i]))return!1;return!0}if(s=Object.keys(t),o=s.length,o!==Object.keys(a).length)return!1;for(i=o;i--!==0;)if(!{}.hasOwnProperty.call(a,s[i]))return!1;for(i=o;i--!==0;){const u=s[i];if(!(u==="_owner"&&t.$$typeof)&&!ku(t[u],a[u]))return!1}return!0}return t!==t&&a!==a}function B3(t){return typeof window>"u"?1:(t.ownerDocument.defaultView||window).devicePixelRatio||1}function T1(t,a){const o=B3(t);return Math.round(a*o)/o}function ef(t){const a=y.useRef(t);return xu(()=>{a.current=t}),a}function $3(t){t===void 0&&(t={});const{placement:a="bottom",strategy:o="absolute",middleware:i=[],platform:s,elements:{reference:u,floating:c}={},transform:d=!0,whileElementsMounted:v,open:m}=t,[A,p]=y.useState({x:0,y:0,strategy:o,placement:a,middlewareData:{},isPositioned:!1}),[C,b]=y.useState(i);ku(C,i)||b(i);const[S,x]=y.useState(null),[w,D]=y.useState(null),T=y.useCallback(K=>{K!==j.current&&(j.current=K,x(K))},[]),R=y.useCallback(K=>{K!==F.current&&(F.current=K,D(K))},[]),_=u||S,N=c||w,j=y.useRef(null),F=y.useRef(null),O=y.useRef(A),I=v!=null,re=ef(v),pe=ef(s),ce=ef(m),de=y.useCallback(()=>{if(!j.current||!F.current)return;const K={placement:a,strategy:o,middleware:C};pe.current&&(K.platform=pe.current),bR(j.current,F.current,K).then(G=>{const se={...G,isPositioned:ce.current!==!1};J.current&&!ku(O.current,se)&&(O.current=se,yd.flushSync(()=>{p(se)}))})},[C,a,o,pe,ce]);xu(()=>{m===!1&&O.current.isPositioned&&(O.current.isPositioned=!1,p(K=>({...K,isPositioned:!1})))},[m]);const J=y.useRef(!1);xu(()=>(J.current=!0,()=>{J.current=!1}),[]),xu(()=>{if(_&&(j.current=_),N&&(F.current=N),_&&N){if(re.current)return re.current(_,N,de);de()}},[_,N,de,re,I]);const fe=y.useMemo(()=>({reference:j,floating:F,setReference:T,setFloating:R}),[T,R]),U=y.useMemo(()=>({reference:_,floating:N}),[_,N]),H=y.useMemo(()=>{const K={position:o,left:0,top:0};if(!U.floating)return K;const G=T1(U.floating,A.x),se=T1(U.floating,A.y);return d?{...K,transform:"translate("+G+"px, "+se+"px)",...B3(U.floating)>=1.5&&{willChange:"transform"}}:{position:o,left:G,top:se}},[o,d,U.floating,A.x,A.y]);return y.useMemo(()=>({...A,update:de,refs:fe,elements:U,floatingStyles:H}),[A,de,fe,U,H])}const xR=t=>{function a(o){return{}.hasOwnProperty.call(o,"current")}return{name:"arrow",options:t,fn(o){const{element:i,padding:s}=typeof t=="function"?t(o):t;return i&&a(i)?i.current!=null?R1({element:i.current,padding:s}).fn(o):{}:i?R1({element:i,padding:s}).fn(o):{}}}},V3=(t,a)=>{const o=mR(t);return{name:o.name,fn:o.fn,options:[t,a]}},q3=(t,a)=>{const o=vR(t);return{name:o.name,fn:o.fn,options:[t,a]}},wR=(t,a)=>({fn:CR(t).fn,options:[t,a]}),_R=(t,a)=>{const o=gR(t);return{name:o.name,fn:o.fn,options:[t,a]}},RR=(t,a)=>{const o=yR(t);return{name:o.name,fn:o.fn,options:[t,a]}},TR=(t,a)=>{const o=AR(t);return{name:o.name,fn:o.fn,options:[t,a]}},G3=(t,a)=>{const o=xR(t);return{name:o.name,fn:o.fn,options:[t,a]}};var MR="Arrow",Y3=y.forwardRef((t,a)=>{const{children:o,width:i=10,height:s=5,...u}=t;return g.jsx(ke.svg,{...u,ref:a,width:i,height:s,viewBox:"0 0 30 10",preserveAspectRatio:"none",children:t.asChild?o:g.jsx("polygon",{points:"0,0 30,0 15,10"})})});Y3.displayName=MR;var DR=Y3,Kd="Popper",[Q3,ac]=ra(Kd),[OR,K3]=Q3(Kd),X3=t=>{const{__scopePopper:a,children:o}=t,[i,s]=y.useState(null);return g.jsx(OR,{scope:a,anchor:i,onAnchorChange:s,children:o})};X3.displayName=Kd;var Z3="PopperAnchor",J3=y.forwardRef((t,a)=>{const{__scopePopper:o,virtualRef:i,...s}=t,u=K3(Z3,o),c=y.useRef(null),d=yt(a,c),v=y.useRef(null);return y.useEffect(()=>{const m=v.current;v.current=i?.current||c.current,m!==v.current&&u.onAnchorChange(v.current)}),i?null:g.jsx(ke.div,{...s,ref:d})});J3.displayName=Z3;var Xd="PopperContent",[NR,LR]=Q3(Xd),W3=y.forwardRef((t,a)=>{const{__scopePopper:o,side:i="bottom",sideOffset:s=0,align:u="center",alignOffset:c=0,arrowPadding:d=0,avoidCollisions:v=!0,collisionBoundary:m=[],collisionPadding:A=0,sticky:p="partial",hideWhenDetached:C=!1,updatePositionStrategy:b="optimized",onPlaced:S,...x}=t,w=K3(Xd,o),[D,T]=y.useState(null),R=yt(a,ue=>T(ue)),[_,N]=y.useState(null),j=T_(_),F=j?.width??0,O=j?.height??0,I=i+(u!=="center"?"-"+u:""),re=typeof A=="number"?A:{top:0,right:0,bottom:0,left:0,...A},pe=Array.isArray(m)?m:[m],ce=pe.length>0,de={padding:re,boundary:pe.filter(FR),altBoundary:ce},{refs:J,floatingStyles:fe,placement:U,isPositioned:H,middlewareData:K}=$3({strategy:"fixed",placement:I,whileElementsMounted:(...ue)=>pR(...ue,{animationFrame:b==="always"}),elements:{reference:w.anchor},middleware:[V3({mainAxis:s+O,alignmentAxis:c}),v&&q3({mainAxis:!0,crossAxis:!1,limiter:p==="partial"?wR():void 0,...de}),v&&_R({...de}),RR({...de,apply:({elements:ue,rects:q,availableWidth:we,availableHeight:lt})=>{const{width:Xe,height:W}=q.reference,te=ue.floating.style;te.setProperty("--radix-popper-available-width",`${we}px`),te.setProperty("--radix-popper-available-height",`${lt}px`),te.setProperty("--radix-popper-anchor-width",`${Xe}px`),te.setProperty("--radix-popper-anchor-height",`${W}px`)}}),_&&G3({element:_,padding:d}),kR({arrowWidth:F,arrowHeight:O}),C&&TR({strategy:"referenceHidden",...de})]}),[G,se]=nC(U),L=on(S);Gn(()=>{H&&L?.()},[H,L]);const $=K.arrow?.x,ne=K.arrow?.y,ie=K.arrow?.centerOffset!==0,[Ae,Se]=y.useState();return Gn(()=>{D&&Se(window.getComputedStyle(D).zIndex)},[D]),g.jsx("div",{ref:J.setFloating,"data-radix-popper-content-wrapper":"",style:{...fe,transform:H?fe.transform:"translate(0, -200%)",minWidth:"max-content",zIndex:Ae,"--radix-popper-transform-origin":[K.transformOrigin?.x,K.transformOrigin?.y].join(" "),...K.hide?.referenceHidden&&{visibility:"hidden",pointerEvents:"none"}},dir:t.dir,children:g.jsx(NR,{scope:o,placedSide:G,onArrowChange:N,arrowX:$,arrowY:ne,shouldHideArrow:ie,children:g.jsx(ke.div,{"data-side":G,"data-align":se,...x,ref:R,style:{...x.style,animation:H?void 0:"none"}})})})});W3.displayName=Xd;var eC="PopperArrow",jR={top:"bottom",right:"left",bottom:"top",left:"right"},tC=y.forwardRef(function(a,o){const{__scopePopper:i,...s}=a,u=LR(eC,i),c=jR[u.placedSide];return g.jsx("span",{ref:u.onArrowChange,style:{position:"absolute",left:u.arrowX,top:u.arrowY,[c]:0,transformOrigin:{top:"",right:"0 0",bottom:"center 0",left:"100% 0"}[u.placedSide],transform:{top:"translateY(100%)",right:"translateY(50%) rotate(90deg) translateX(-50%)",bottom:"rotate(180deg)",left:"translateY(50%) rotate(-90deg) translateX(50%)"}[u.placedSide],visibility:u.shouldHideArrow?"hidden":void 0},children:g.jsx(DR,{...s,ref:o,style:{...s.style,display:"block"}})})});tC.displayName=eC;function FR(t){return t!==null}var kR=t=>({name:"transformOrigin",options:t,fn(a){const{placement:o,rects:i,middlewareData:s}=a,c=s.arrow?.centerOffset!==0,d=c?0:t.arrowWidth,v=c?0:t.arrowHeight,[m,A]=nC(o),p={start:"0%",center:"50%",end:"100%"}[A],C=(s.arrow?.x??0)+d/2,b=(s.arrow?.y??0)+v/2;let S="",x="";return m==="bottom"?(S=c?p:`${C}px`,x=`${-v}px`):m==="top"?(S=c?p:`${C}px`,x=`${i.floating.height+v}px`):m==="right"?(S=`${-v}px`,x=c?p:`${b}px`):m==="left"&&(S=`${i.floating.width+v}px`,x=c?p:`${b}px`),{data:{x:S,y:x}}}});function nC(t){const[a,o="center"]=t.split("-");return[a,o]}var aC=X3,Zd=J3,rC=W3,oC=tC,tf="rovingFocusGroup.onEntryFocus",zR={bubbles:!1,cancelable:!0},Nl="RovingFocusGroup",[Vf,iC,UR]=Dl(Nl),[PR,rc]=ra(Nl,[UR]),[IR,HR]=PR(Nl),lC=y.forwardRef((t,a)=>g.jsx(Vf.Provider,{scope:t.__scopeRovingFocusGroup,children:g.jsx(Vf.Slot,{scope:t.__scopeRovingFocusGroup,children:g.jsx(BR,{...t,ref:a})})}));lC.displayName=Nl;var BR=y.forwardRef((t,a)=>{const{__scopeRovingFocusGroup:o,orientation:i,loop:s=!1,dir:u,currentTabStopId:c,defaultCurrentTabStopId:d,onCurrentTabStopIdChange:v,onEntryFocus:m,preventScrollOnEntryFocus:A=!1,...p}=t,C=y.useRef(null),b=yt(a,C),S=Ml(u),[x,w]=Ca({prop:c,defaultProp:d??null,onChange:v,caller:Nl}),[D,T]=y.useState(!1),R=on(m),_=iC(o),N=y.useRef(!1),[j,F]=y.useState(0);return y.useEffect(()=>{const O=C.current;if(O)return O.addEventListener(tf,R),()=>O.removeEventListener(tf,R)},[R]),g.jsx(IR,{scope:o,orientation:i,dir:S,loop:s,currentTabStopId:x,onItemFocus:y.useCallback(O=>w(O),[w]),onItemShiftTab:y.useCallback(()=>T(!0),[]),onFocusableItemAdd:y.useCallback(()=>F(O=>O+1),[]),onFocusableItemRemove:y.useCallback(()=>F(O=>O-1),[]),children:g.jsx(ke.div,{tabIndex:D||j===0?-1:0,"data-orientation":i,...p,ref:b,style:{outline:"none",...t.style},onMouseDown:Re(t.onMouseDown,()=>{N.current=!0}),onFocus:Re(t.onFocus,O=>{const I=!N.current;if(O.target===O.currentTarget&&I&&!D){const re=new CustomEvent(tf,zR);if(O.currentTarget.dispatchEvent(re),!re.defaultPrevented){const pe=_().filter(U=>U.focusable),ce=pe.find(U=>U.active),de=pe.find(U=>U.id===x),fe=[ce,de,...pe].filter(Boolean).map(U=>U.ref.current);cC(fe,A)}}N.current=!1}),onBlur:Re(t.onBlur,()=>T(!1))})})}),sC="RovingFocusGroupItem",uC=y.forwardRef((t,a)=>{const{__scopeRovingFocusGroup:o,focusable:i=!0,active:s=!1,tabStopId:u,children:c,...d}=t,v=$n(),m=u||v,A=HR(sC,o),p=A.currentTabStopId===m,C=iC(o),{onFocusableItemAdd:b,onFocusableItemRemove:S,currentTabStopId:x}=A;return y.useEffect(()=>{if(i)return b(),()=>S()},[i,b,S]),g.jsx(Vf.ItemSlot,{scope:o,id:m,focusable:i,active:s,children:g.jsx(ke.span,{tabIndex:p?0:-1,"data-orientation":A.orientation,...d,ref:a,onMouseDown:Re(t.onMouseDown,w=>{i?A.onItemFocus(m):w.preventDefault()}),onFocus:Re(t.onFocus,()=>A.onItemFocus(m)),onKeyDown:Re(t.onKeyDown,w=>{if(w.key==="Tab"&&w.shiftKey){A.onItemShiftTab();return}if(w.target!==w.currentTarget)return;const D=qR(w,A.orientation,A.dir);if(D!==void 0){if(w.metaKey||w.ctrlKey||w.altKey||w.shiftKey)return;w.preventDefault();let R=C().filter(_=>_.focusable).map(_=>_.ref.current);if(D==="last")R.reverse();else if(D==="prev"||D==="next"){D==="prev"&&R.reverse();const _=R.indexOf(w.currentTarget);R=A.loop?GR(R,_+1):R.slice(_+1)}setTimeout(()=>cC(R))}}),children:typeof c=="function"?c({isCurrentTabStop:p,hasTabStop:x!=null}):c})})});uC.displayName=sC;var $R={ArrowLeft:"prev",ArrowUp:"prev",ArrowRight:"next",ArrowDown:"next",PageUp:"first",Home:"first",PageDown:"last",End:"last"};function VR(t,a){return a!=="rtl"?t:t==="ArrowLeft"?"ArrowRight":t==="ArrowRight"?"ArrowLeft":t}function qR(t,a,o){const i=VR(t.key,o);if(!(a==="vertical"&&["ArrowLeft","ArrowRight"].includes(i))&&!(a==="horizontal"&&["ArrowUp","ArrowDown"].includes(i)))return $R[i]}function cC(t,a=!1){const o=document.activeElement;for(const i of t)if(i===o||(i.focus({preventScroll:a}),document.activeElement!==o))return}function GR(t,a){return t.map((o,i)=>t[(a+i)%t.length])}var fC=lC,dC=uC,qf=["Enter"," "],YR=["ArrowDown","PageUp","Home"],hC=["ArrowUp","PageDown","End"],QR=[...YR,...hC],KR={ltr:[...qf,"ArrowRight"],rtl:[...qf,"ArrowLeft"]},XR={ltr:["ArrowLeft"],rtl:["ArrowRight"]},Ll="Menu",[Cl,ZR,JR]=Dl(Ll),[oo,pC]=ra(Ll,[JR,ac,rc]),oc=ac(),mC=rc(),[WR,io]=oo(Ll),[eT,jl]=oo(Ll),vC=t=>{const{__scopeMenu:a,open:o=!1,children:i,dir:s,onOpenChange:u,modal:c=!0}=t,d=oc(a),[v,m]=y.useState(null),A=y.useRef(!1),p=on(u),C=Ml(s);return y.useEffect(()=>{const b=()=>{A.current=!0,document.addEventListener("pointerdown",S,{capture:!0,once:!0}),document.addEventListener("pointermove",S,{capture:!0,once:!0})},S=()=>A.current=!1;return document.addEventListener("keydown",b,{capture:!0}),()=>{document.removeEventListener("keydown",b,{capture:!0}),document.removeEventListener("pointerdown",S,{capture:!0}),document.removeEventListener("pointermove",S,{capture:!0})}},[]),g.jsx(aC,{...d,children:g.jsx(WR,{scope:a,open:o,onOpenChange:p,content:v,onContentChange:m,children:g.jsx(eT,{scope:a,onClose:y.useCallback(()=>p(!1),[p]),isUsingKeyboardRef:A,dir:C,modal:c,children:i})})})};vC.displayName=Ll;var tT="MenuAnchor",Jd=y.forwardRef((t,a)=>{const{__scopeMenu:o,...i}=t,s=oc(o);return g.jsx(Zd,{...s,...i,ref:a})});Jd.displayName=tT;var Wd="MenuPortal",[nT,gC]=oo(Wd,{forceMount:void 0}),yC=t=>{const{__scopeMenu:a,forceMount:o,children:i,container:s}=t,u=io(Wd,a);return g.jsx(nT,{scope:a,forceMount:o,children:g.jsx(ln,{present:o||u.open,children:g.jsx(qu,{asChild:!0,container:s,children:i})})})};yC.displayName=Wd;var Vn="MenuContent",[aT,eh]=oo(Vn),AC=y.forwardRef((t,a)=>{const o=gC(Vn,t.__scopeMenu),{forceMount:i=o.forceMount,...s}=t,u=io(Vn,t.__scopeMenu),c=jl(Vn,t.__scopeMenu);return g.jsx(Cl.Provider,{scope:t.__scopeMenu,children:g.jsx(ln,{present:i||u.open,children:g.jsx(Cl.Slot,{scope:t.__scopeMenu,children:c.modal?g.jsx(rT,{...s,ref:a}):g.jsx(oT,{...s,ref:a})})})})}),rT=y.forwardRef((t,a)=>{const o=io(Vn,t.__scopeMenu),i=y.useRef(null),s=yt(a,i);return y.useEffect(()=>{const u=i.current;if(u)return Cd(u)},[]),g.jsx(th,{...t,ref:s,trapFocus:o.open,disableOutsidePointerEvents:o.open,disableOutsideScroll:!0,onFocusOutside:Re(t.onFocusOutside,u=>u.preventDefault(),{checkForDefaultPrevented:!1}),onDismiss:()=>o.onOpenChange(!1)})}),oT=y.forwardRef((t,a)=>{const o=io(Vn,t.__scopeMenu);return g.jsx(th,{...t,ref:a,trapFocus:!1,disableOutsidePointerEvents:!1,disableOutsideScroll:!1,onDismiss:()=>o.onOpenChange(!1)})}),iT=ai("MenuContent.ScrollLock"),th=y.forwardRef((t,a)=>{const{__scopeMenu:o,loop:i=!1,trapFocus:s,onOpenAutoFocus:u,onCloseAutoFocus:c,disableOutsidePointerEvents:d,onEntryFocus:v,onEscapeKeyDown:m,onPointerDownOutside:A,onFocusOutside:p,onInteractOutside:C,onDismiss:b,disableOutsideScroll:S,...x}=t,w=io(Vn,o),D=jl(Vn,o),T=oc(o),R=mC(o),_=ZR(o),[N,j]=y.useState(null),F=y.useRef(null),O=yt(a,F,w.onContentChange),I=y.useRef(0),re=y.useRef(""),pe=y.useRef(0),ce=y.useRef(null),de=y.useRef("right"),J=y.useRef(0),fe=S?Yu:y.Fragment,U=S?{as:iT,allowPinchZoom:!0}:void 0,H=G=>{const se=re.current+G,L=_().filter(ue=>!ue.disabled),$=document.activeElement,ne=L.find(ue=>ue.ref.current===$)?.textValue,ie=L.map(ue=>ue.textValue),Ae=yT(ie,se,ne),Se=L.find(ue=>ue.textValue===Ae)?.ref.current;(function ue(q){re.current=q,window.clearTimeout(I.current),q!==""&&(I.current=window.setTimeout(()=>ue(""),1e3))})(se),Se&&setTimeout(()=>Se.focus())};y.useEffect(()=>()=>window.clearTimeout(I.current),[]),Ad();const K=y.useCallback(G=>de.current===ce.current?.side&&CT(G,ce.current?.area),[]);return g.jsx(aT,{scope:o,searchRef:re,onItemEnter:y.useCallback(G=>{K(G)&&G.preventDefault()},[K]),onItemLeave:y.useCallback(G=>{K(G)||(F.current?.focus(),j(null))},[K]),onTriggerLeave:y.useCallback(G=>{K(G)&&G.preventDefault()},[K]),pointerGraceTimerRef:pe,onPointerGraceIntentChange:y.useCallback(G=>{ce.current=G},[]),children:g.jsx(fe,{...U,children:g.jsx(Vu,{asChild:!0,trapped:s,onMountAutoFocus:Re(u,G=>{G.preventDefault(),F.current?.focus({preventScroll:!0})}),onUnmountAutoFocus:c,children:g.jsx(Tl,{asChild:!0,disableOutsidePointerEvents:d,onEscapeKeyDown:m,onPointerDownOutside:A,onFocusOutside:p,onInteractOutside:C,onDismiss:b,children:g.jsx(fC,{asChild:!0,...R,dir:D.dir,orientation:"vertical",loop:i,currentTabStopId:N,onCurrentTabStopIdChange:j,onEntryFocus:Re(v,G=>{D.isUsingKeyboardRef.current||G.preventDefault()}),preventScrollOnEntryFocus:!0,children:g.jsx(rC,{role:"menu","aria-orientation":"vertical","data-state":FC(w.open),"data-radix-menu-content":"",dir:D.dir,...T,...x,ref:O,style:{outline:"none",...x.style},onKeyDown:Re(x.onKeyDown,G=>{const L=G.target.closest("[data-radix-menu-content]")===G.currentTarget,$=G.ctrlKey||G.altKey||G.metaKey,ne=G.key.length===1;L&&(G.key==="Tab"&&G.preventDefault(),!$&&ne&&H(G.key));const ie=F.current;if(G.target!==ie||!QR.includes(G.key))return;G.preventDefault();const Se=_().filter(ue=>!ue.disabled).map(ue=>ue.ref.current);hC.includes(G.key)&&Se.reverse(),vT(Se)}),onBlur:Re(t.onBlur,G=>{G.currentTarget.contains(G.target)||(window.clearTimeout(I.current),re.current="")}),onPointerMove:Re(t.onPointerMove,bl(G=>{const se=G.target,L=J.current!==G.clientX;if(G.currentTarget.contains(se)&&L){const $=G.clientX>J.current?"right":"left";de.current=$,J.current=G.clientX}}))})})})})})})});AC.displayName=Vn;var lT="MenuGroup",nh=y.forwardRef((t,a)=>{const{__scopeMenu:o,...i}=t;return g.jsx(ke.div,{role:"group",...i,ref:a})});nh.displayName=lT;var sT="MenuLabel",CC=y.forwardRef((t,a)=>{const{__scopeMenu:o,...i}=t;return g.jsx(ke.div,{...i,ref:a})});CC.displayName=sT;var zu="MenuItem",M1="menu.itemSelect",ic=y.forwardRef((t,a)=>{const{disabled:o=!1,onSelect:i,...s}=t,u=y.useRef(null),c=jl(zu,t.__scopeMenu),d=eh(zu,t.__scopeMenu),v=yt(a,u),m=y.useRef(!1),A=()=>{const p=u.current;if(!o&&p){const C=new CustomEvent(M1,{bubbles:!0,cancelable:!0});p.addEventListener(M1,b=>i?.(b),{once:!0}),_u(p,C),C.defaultPrevented?m.current=!1:c.onClose()}};return g.jsx(bC,{...s,ref:v,disabled:o,onClick:Re(t.onClick,A),onPointerDown:p=>{t.onPointerDown?.(p),m.current=!0},onPointerUp:Re(t.onPointerUp,p=>{m.current||p.currentTarget?.click()}),onKeyDown:Re(t.onKeyDown,p=>{const C=d.searchRef.current!=="";o||C&&p.key===" "||qf.includes(p.key)&&(p.currentTarget.click(),p.preventDefault())})})});ic.displayName=zu;var bC=y.forwardRef((t,a)=>{const{__scopeMenu:o,disabled:i=!1,textValue:s,...u}=t,c=eh(zu,o),d=mC(o),v=y.useRef(null),m=yt(a,v),[A,p]=y.useState(!1),[C,b]=y.useState("");return y.useEffect(()=>{const S=v.current;S&&b((S.textContent??"").trim())},[u.children]),g.jsx(Cl.ItemSlot,{scope:o,disabled:i,textValue:s??C,children:g.jsx(dC,{asChild:!0,...d,focusable:!i,children:g.jsx(ke.div,{role:"menuitem","data-highlighted":A?"":void 0,"aria-disabled":i||void 0,"data-disabled":i?"":void 0,...u,ref:m,onPointerMove:Re(t.onPointerMove,bl(S=>{i?c.onItemLeave(S):(c.onItemEnter(S),S.defaultPrevented||S.currentTarget.focus({preventScroll:!0}))})),onPointerLeave:Re(t.onPointerLeave,bl(S=>c.onItemLeave(S))),onFocus:Re(t.onFocus,()=>p(!0)),onBlur:Re(t.onBlur,()=>p(!1))})})})}),uT="MenuCheckboxItem",EC=y.forwardRef((t,a)=>{const{checked:o=!1,onCheckedChange:i,...s}=t;return g.jsx(RC,{scope:t.__scopeMenu,checked:o,children:g.jsx(ic,{role:"menuitemcheckbox","aria-checked":Uu(o)?"mixed":o,...s,ref:a,"data-state":rh(o),onSelect:Re(s.onSelect,()=>i?.(Uu(o)?!0:!o),{checkForDefaultPrevented:!1})})})});EC.displayName=uT;var SC="MenuRadioGroup",[cT,fT]=oo(SC,{value:void 0,onValueChange:()=>{}}),xC=y.forwardRef((t,a)=>{const{value:o,onValueChange:i,...s}=t,u=on(i);return g.jsx(cT,{scope:t.__scopeMenu,value:o,onValueChange:u,children:g.jsx(nh,{...s,ref:a})})});xC.displayName=SC;var wC="MenuRadioItem",_C=y.forwardRef((t,a)=>{const{value:o,...i}=t,s=fT(wC,t.__scopeMenu),u=o===s.value;return g.jsx(RC,{scope:t.__scopeMenu,checked:u,children:g.jsx(ic,{role:"menuitemradio","aria-checked":u,...i,ref:a,"data-state":rh(u),onSelect:Re(i.onSelect,()=>s.onValueChange?.(o),{checkForDefaultPrevented:!1})})})});_C.displayName=wC;var ah="MenuItemIndicator",[RC,dT]=oo(ah,{checked:!1}),TC=y.forwardRef((t,a)=>{const{__scopeMenu:o,forceMount:i,...s}=t,u=dT(ah,o);return g.jsx(ln,{present:i||Uu(u.checked)||u.checked===!0,children:g.jsx(ke.span,{...s,ref:a,"data-state":rh(u.checked)})})});TC.displayName=ah;var hT="MenuSeparator",MC=y.forwardRef((t,a)=>{const{__scopeMenu:o,...i}=t;return g.jsx(ke.div,{role:"separator","aria-orientation":"horizontal",...i,ref:a})});MC.displayName=hT;var pT="MenuArrow",DC=y.forwardRef((t,a)=>{const{__scopeMenu:o,...i}=t,s=oc(o);return g.jsx(oC,{...s,...i,ref:a})});DC.displayName=pT;var mT="MenuSub",[wL,OC]=oo(mT),cl="MenuSubTrigger",NC=y.forwardRef((t,a)=>{const o=io(cl,t.__scopeMenu),i=jl(cl,t.__scopeMenu),s=OC(cl,t.__scopeMenu),u=eh(cl,t.__scopeMenu),c=y.useRef(null),{pointerGraceTimerRef:d,onPointerGraceIntentChange:v}=u,m={__scopeMenu:t.__scopeMenu},A=y.useCallback(()=>{c.current&&window.clearTimeout(c.current),c.current=null},[]);return y.useEffect(()=>A,[A]),y.useEffect(()=>{const p=d.current;return()=>{window.clearTimeout(p),v(null)}},[d,v]),g.jsx(Jd,{asChild:!0,...m,children:g.jsx(bC,{id:s.triggerId,"aria-haspopup":"menu","aria-expanded":o.open,"aria-controls":s.contentId,"data-state":FC(o.open),...t,ref:di(a,s.onTriggerChange),onClick:p=>{t.onClick?.(p),!(t.disabled||p.defaultPrevented)&&(p.currentTarget.focus(),o.open||o.onOpenChange(!0))},onPointerMove:Re(t.onPointerMove,bl(p=>{u.onItemEnter(p),!p.defaultPrevented&&!t.disabled&&!o.open&&!c.current&&(u.onPointerGraceIntentChange(null),c.current=window.setTimeout(()=>{o.onOpenChange(!0),A()},100))})),onPointerLeave:Re(t.onPointerLeave,bl(p=>{A();const C=o.content?.getBoundingClientRect();if(C){const b=o.content?.dataset.side,S=b==="right",x=S?-5:5,w=C[S?"left":"right"],D=C[S?"right":"left"];u.onPointerGraceIntentChange({area:[{x:p.clientX+x,y:p.clientY},{x:w,y:C.top},{x:D,y:C.top},{x:D,y:C.bottom},{x:w,y:C.bottom}],side:b}),window.clearTimeout(d.current),d.current=window.setTimeout(()=>u.onPointerGraceIntentChange(null),300)}else{if(u.onTriggerLeave(p),p.defaultPrevented)return;u.onPointerGraceIntentChange(null)}})),onKeyDown:Re(t.onKeyDown,p=>{const C=u.searchRef.current!=="";t.disabled||C&&p.key===" "||KR[i.dir].includes(p.key)&&(o.onOpenChange(!0),o.content?.focus(),p.preventDefault())})})})});NC.displayName=cl;var LC="MenuSubContent",jC=y.forwardRef((t,a)=>{const o=gC(Vn,t.__scopeMenu),{forceMount:i=o.forceMount,...s}=t,u=io(Vn,t.__scopeMenu),c=jl(Vn,t.__scopeMenu),d=OC(LC,t.__scopeMenu),v=y.useRef(null),m=yt(a,v);return g.jsx(Cl.Provider,{scope:t.__scopeMenu,children:g.jsx(ln,{present:i||u.open,children:g.jsx(Cl.Slot,{scope:t.__scopeMenu,children:g.jsx(th,{id:d.contentId,"aria-labelledby":d.triggerId,...s,ref:m,align:"start",side:c.dir==="rtl"?"left":"right",disableOutsidePointerEvents:!1,disableOutsideScroll:!1,trapFocus:!1,onOpenAutoFocus:A=>{c.isUsingKeyboardRef.current&&v.current?.focus(),A.preventDefault()},onCloseAutoFocus:A=>A.preventDefault(),onFocusOutside:Re(t.onFocusOutside,A=>{A.target!==d.trigger&&u.onOpenChange(!1)}),onEscapeKeyDown:Re(t.onEscapeKeyDown,A=>{c.onClose(),A.preventDefault()}),onKeyDown:Re(t.onKeyDown,A=>{const p=A.currentTarget.contains(A.target),C=XR[c.dir].includes(A.key);p&&C&&(u.onOpenChange(!1),d.trigger?.focus(),A.preventDefault())})})})})})});jC.displayName=LC;function FC(t){return t?"open":"closed"}function Uu(t){return t==="indeterminate"}function rh(t){return Uu(t)?"indeterminate":t?"checked":"unchecked"}function vT(t){const a=document.activeElement;for(const o of t)if(o===a||(o.focus(),document.activeElement!==a))return}function gT(t,a){return t.map((o,i)=>t[(a+i)%t.length])}function yT(t,a,o){const s=a.length>1&&Array.from(a).every(m=>m===a[0])?a[0]:a,u=o?t.indexOf(o):-1;let c=gT(t,Math.max(u,0));s.length===1&&(c=c.filter(m=>m!==o));const v=c.find(m=>m.toLowerCase().startsWith(s.toLowerCase()));return v!==o?v:void 0}function AT(t,a){const{x:o,y:i}=t;let s=!1;for(let u=0,c=a.length-1;u<a.length;c=u++){const d=a[u],v=a[c],m=d.x,A=d.y,p=v.x,C=v.y;A>i!=C>i&&o<(p-m)*(i-A)/(C-A)+m&&(s=!s)}return s}function CT(t,a){if(!a)return!1;const o={x:t.clientX,y:t.clientY};return AT(o,a)}function bl(t){return a=>a.pointerType==="mouse"?t(a):void 0}var bT=vC,ET=Jd,ST=yC,xT=AC,wT=nh,_T=CC,RT=ic,TT=EC,MT=xC,DT=_C,OT=TC,NT=MC,LT=DC,jT=NC,FT=jC,lc="DropdownMenu",[kT]=ra(lc,[pC]),cn=pC(),[zT,kC]=kT(lc),zC=t=>{const{__scopeDropdownMenu:a,children:o,dir:i,open:s,defaultOpen:u,onOpenChange:c,modal:d=!0}=t,v=cn(a),m=y.useRef(null),[A,p]=Ca({prop:s,defaultProp:u??!1,onChange:c,caller:lc});return g.jsx(zT,{scope:a,triggerId:$n(),triggerRef:m,contentId:$n(),open:A,onOpenChange:p,onOpenToggle:y.useCallback(()=>p(C=>!C),[p]),modal:d,children:g.jsx(bT,{...v,open:A,onOpenChange:p,dir:i,modal:d,children:o})})};zC.displayName=lc;var UC="DropdownMenuTrigger",PC=y.forwardRef((t,a)=>{const{__scopeDropdownMenu:o,disabled:i=!1,...s}=t,u=kC(UC,o),c=cn(o);return g.jsx(ET,{asChild:!0,...c,children:g.jsx(ke.button,{type:"button",id:u.triggerId,"aria-haspopup":"menu","aria-expanded":u.open,"aria-controls":u.open?u.contentId:void 0,"data-state":u.open?"open":"closed","data-disabled":i?"":void 0,disabled:i,...s,ref:di(a,u.triggerRef),onPointerDown:Re(t.onPointerDown,d=>{!i&&d.button===0&&d.ctrlKey===!1&&(u.onOpenToggle(),u.open||d.preventDefault())}),onKeyDown:Re(t.onKeyDown,d=>{i||(["Enter"," "].includes(d.key)&&u.onOpenToggle(),d.key==="ArrowDown"&&u.onOpenChange(!0),["Enter"," ","ArrowDown"].includes(d.key)&&d.preventDefault())})})})});PC.displayName=UC;var UT="DropdownMenuPortal",IC=t=>{const{__scopeDropdownMenu:a,...o}=t,i=cn(a);return g.jsx(ST,{...i,...o})};IC.displayName=UT;var HC="DropdownMenuContent",BC=y.forwardRef((t,a)=>{const{__scopeDropdownMenu:o,...i}=t,s=kC(HC,o),u=cn(o),c=y.useRef(!1);return g.jsx(xT,{id:s.contentId,"aria-labelledby":s.triggerId,...u,...i,ref:a,onCloseAutoFocus:Re(t.onCloseAutoFocus,d=>{c.current||s.triggerRef.current?.focus(),c.current=!1,d.preventDefault()}),onInteractOutside:Re(t.onInteractOutside,d=>{const v=d.detail.originalEvent,m=v.button===0&&v.ctrlKey===!0,A=v.button===2||m;(!s.modal||A)&&(c.current=!0)}),style:{...t.style,"--radix-dropdown-menu-content-transform-origin":"var(--radix-popper-transform-origin)","--radix-dropdown-menu-content-available-width":"var(--radix-popper-available-width)","--radix-dropdown-menu-content-available-height":"var(--radix-popper-available-height)","--radix-dropdown-menu-trigger-width":"var(--radix-popper-anchor-width)","--radix-dropdown-menu-trigger-height":"var(--radix-popper-anchor-height)"}})});BC.displayName=HC;var PT="DropdownMenuGroup",IT=y.forwardRef((t,a)=>{const{__scopeDropdownMenu:o,...i}=t,s=cn(o);return g.jsx(wT,{...s,...i,ref:a})});IT.displayName=PT;var HT="DropdownMenuLabel",BT=y.forwardRef((t,a)=>{const{__scopeDropdownMenu:o,...i}=t,s=cn(o);return g.jsx(_T,{...s,...i,ref:a})});BT.displayName=HT;var $T="DropdownMenuItem",$C=y.forwardRef((t,a)=>{const{__scopeDropdownMenu:o,...i}=t,s=cn(o);return g.jsx(RT,{...s,...i,ref:a})});$C.displayName=$T;var VT="DropdownMenuCheckboxItem",qT=y.forwardRef((t,a)=>{const{__scopeDropdownMenu:o,...i}=t,s=cn(o);return g.jsx(TT,{...s,...i,ref:a})});qT.displayName=VT;var GT="DropdownMenuRadioGroup",YT=y.forwardRef((t,a)=>{const{__scopeDropdownMenu:o,...i}=t,s=cn(o);return g.jsx(MT,{...s,...i,ref:a})});YT.displayName=GT;var QT="DropdownMenuRadioItem",KT=y.forwardRef((t,a)=>{const{__scopeDropdownMenu:o,...i}=t,s=cn(o);return g.jsx(DT,{...s,...i,ref:a})});KT.displayName=QT;var XT="DropdownMenuItemIndicator",ZT=y.forwardRef((t,a)=>{const{__scopeDropdownMenu:o,...i}=t,s=cn(o);return g.jsx(OT,{...s,...i,ref:a})});ZT.displayName=XT;var JT="DropdownMenuSeparator",WT=y.forwardRef((t,a)=>{const{__scopeDropdownMenu:o,...i}=t,s=cn(o);return g.jsx(NT,{...s,...i,ref:a})});WT.displayName=JT;var eM="DropdownMenuArrow",tM=y.forwardRef((t,a)=>{const{__scopeDropdownMenu:o,...i}=t,s=cn(o);return g.jsx(LT,{...s,...i,ref:a})});tM.displayName=eM;var nM="DropdownMenuSubTrigger",aM=y.forwardRef((t,a)=>{const{__scopeDropdownMenu:o,...i}=t,s=cn(o);return g.jsx(jT,{...s,...i,ref:a})});aM.displayName=nM;var rM="DropdownMenuSubContent",oM=y.forwardRef((t,a)=>{const{__scopeDropdownMenu:o,...i}=t,s=cn(o);return g.jsx(FT,{...s,...i,ref:a,style:{...t.style,"--radix-dropdown-menu-content-transform-origin":"var(--radix-popper-transform-origin)","--radix-dropdown-menu-content-available-width":"var(--radix-popper-available-width)","--radix-dropdown-menu-content-available-height":"var(--radix-popper-available-height)","--radix-dropdown-menu-trigger-width":"var(--radix-popper-anchor-width)","--radix-dropdown-menu-trigger-height":"var(--radix-popper-anchor-height)"}})});oM.displayName=rM;var iM=zC,lM=PC,sM=IC,uM=BC,cM=$C,sc="Popover",[VC]=ra(sc,[ac]),Fl=ac(),[fM,Rr]=VC(sc),qC=t=>{const{__scopePopover:a,children:o,open:i,defaultOpen:s,onOpenChange:u,modal:c=!1}=t,d=Fl(a),v=y.useRef(null),[m,A]=y.useState(!1),[p,C]=Ca({prop:i,defaultProp:s??!1,onChange:u,caller:sc});return g.jsx(aC,{...d,children:g.jsx(fM,{scope:a,contentId:$n(),triggerRef:v,open:p,onOpenChange:C,onOpenToggle:y.useCallback(()=>C(b=>!b),[C]),hasCustomAnchor:m,onCustomAnchorAdd:y.useCallback(()=>A(!0),[]),onCustomAnchorRemove:y.useCallback(()=>A(!1),[]),modal:c,children:o})})};qC.displayName=sc;var GC="PopoverAnchor",dM=y.forwardRef((t,a)=>{const{__scopePopover:o,...i}=t,s=Rr(GC,o),u=Fl(o),{onCustomAnchorAdd:c,onCustomAnchorRemove:d}=s;return y.useEffect(()=>(c(),()=>d()),[c,d]),g.jsx(Zd,{...u,...i,ref:a})});dM.displayName=GC;var YC="PopoverTrigger",QC=y.forwardRef((t,a)=>{const{__scopePopover:o,...i}=t,s=Rr(YC,o),u=Fl(o),c=yt(a,s.triggerRef),d=g.jsx(ke.button,{type:"button","aria-haspopup":"dialog","aria-expanded":s.open,"aria-controls":s.contentId,"data-state":WC(s.open),...i,ref:c,onClick:Re(t.onClick,s.onOpenToggle)});return s.hasCustomAnchor?d:g.jsx(Zd,{asChild:!0,...u,children:d})});QC.displayName=YC;var oh="PopoverPortal",[hM,pM]=VC(oh,{forceMount:void 0}),KC=t=>{const{__scopePopover:a,forceMount:o,children:i,container:s}=t,u=Rr(oh,a);return g.jsx(hM,{scope:a,forceMount:o,children:g.jsx(ln,{present:o||u.open,children:g.jsx(qu,{asChild:!0,container:s,children:i})})})};KC.displayName=oh;var ii="PopoverContent",XC=y.forwardRef((t,a)=>{const o=pM(ii,t.__scopePopover),{forceMount:i=o.forceMount,...s}=t,u=Rr(ii,t.__scopePopover);return g.jsx(ln,{present:i||u.open,children:u.modal?g.jsx(vM,{...s,ref:a}):g.jsx(gM,{...s,ref:a})})});XC.displayName=ii;var mM=ai("PopoverContent.RemoveScroll"),vM=y.forwardRef((t,a)=>{const o=Rr(ii,t.__scopePopover),i=y.useRef(null),s=yt(a,i),u=y.useRef(!1);return y.useEffect(()=>{const c=i.current;if(c)return Cd(c)},[]),g.jsx(Yu,{as:mM,allowPinchZoom:!0,children:g.jsx(ZC,{...t,ref:s,trapFocus:o.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:Re(t.onCloseAutoFocus,c=>{c.preventDefault(),u.current||o.triggerRef.current?.focus()}),onPointerDownOutside:Re(t.onPointerDownOutside,c=>{const d=c.detail.originalEvent,v=d.button===0&&d.ctrlKey===!0,m=d.button===2||v;u.current=m},{checkForDefaultPrevented:!1}),onFocusOutside:Re(t.onFocusOutside,c=>c.preventDefault(),{checkForDefaultPrevented:!1})})})}),gM=y.forwardRef((t,a)=>{const o=Rr(ii,t.__scopePopover),i=y.useRef(!1),s=y.useRef(!1);return g.jsx(ZC,{...t,ref:a,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:u=>{t.onCloseAutoFocus?.(u),u.defaultPrevented||(i.current||o.triggerRef.current?.focus(),u.preventDefault()),i.current=!1,s.current=!1},onInteractOutside:u=>{t.onInteractOutside?.(u),u.defaultPrevented||(i.current=!0,u.detail.originalEvent.type==="pointerdown"&&(s.current=!0));const c=u.target;o.triggerRef.current?.contains(c)&&u.preventDefault(),u.detail.originalEvent.type==="focusin"&&s.current&&u.preventDefault()}})}),ZC=y.forwardRef((t,a)=>{const{__scopePopover:o,trapFocus:i,onOpenAutoFocus:s,onCloseAutoFocus:u,disableOutsidePointerEvents:c,onEscapeKeyDown:d,onPointerDownOutside:v,onFocusOutside:m,onInteractOutside:A,...p}=t,C=Rr(ii,o),b=Fl(o);return Ad(),g.jsx(Vu,{asChild:!0,loop:!0,trapped:i,onMountAutoFocus:s,onUnmountAutoFocus:u,children:g.jsx(Tl,{asChild:!0,disableOutsidePointerEvents:c,onInteractOutside:A,onEscapeKeyDown:d,onPointerDownOutside:v,onFocusOutside:m,onDismiss:()=>C.onOpenChange(!1),children:g.jsx(rC,{"data-state":WC(C.open),role:"dialog",id:C.contentId,...b,...p,ref:a,style:{...p.style,"--radix-popover-content-transform-origin":"var(--radix-popper-transform-origin)","--radix-popover-content-available-width":"var(--radix-popper-available-width)","--radix-popover-content-available-height":"var(--radix-popper-available-height)","--radix-popover-trigger-width":"var(--radix-popper-anchor-width)","--radix-popover-trigger-height":"var(--radix-popper-anchor-height)"}})})})}),JC="PopoverClose",yM=y.forwardRef((t,a)=>{const{__scopePopover:o,...i}=t,s=Rr(JC,o);return g.jsx(ke.button,{type:"button",...i,ref:a,onClick:Re(t.onClick,()=>s.onOpenChange(!1))})});yM.displayName=JC;var AM="PopoverArrow",CM=y.forwardRef((t,a)=>{const{__scopePopover:o,...i}=t,s=Fl(o);return g.jsx(oC,{...s,...i,ref:a})});CM.displayName=AM;function WC(t){return t?"open":"closed"}var bM=qC,EM=QC,SM=KC,xM=XC,uc="Tabs",[wM]=ra(uc,[rc]),e6=rc(),[_M,ih]=wM(uc),t6=y.forwardRef((t,a)=>{const{__scopeTabs:o,value:i,onValueChange:s,defaultValue:u,orientation:c="horizontal",dir:d,activationMode:v="automatic",...m}=t,A=Ml(d),[p,C]=Ca({prop:i,onChange:s,defaultProp:u??"",caller:uc});return g.jsx(_M,{scope:o,baseId:$n(),value:p,onValueChange:C,orientation:c,dir:A,activationMode:v,children:g.jsx(ke.div,{dir:A,"data-orientation":c,...m,ref:a})})});t6.displayName=uc;var n6="TabsList",a6=y.forwardRef((t,a)=>{const{__scopeTabs:o,loop:i=!0,...s}=t,u=ih(n6,o),c=e6(o);return g.jsx(fC,{asChild:!0,...c,orientation:u.orientation,dir:u.dir,loop:i,children:g.jsx(ke.div,{role:"tablist","aria-orientation":u.orientation,...s,ref:a})})});a6.displayName=n6;var r6="TabsTrigger",o6=y.forwardRef((t,a)=>{const{__scopeTabs:o,value:i,disabled:s=!1,...u}=t,c=ih(r6,o),d=e6(o),v=s6(c.baseId,i),m=u6(c.baseId,i),A=i===c.value;return g.jsx(dC,{asChild:!0,...d,focusable:!s,active:A,children:g.jsx(ke.button,{type:"button",role:"tab","aria-selected":A,"aria-controls":m,"data-state":A?"active":"inactive","data-disabled":s?"":void 0,disabled:s,id:v,...u,ref:a,onMouseDown:Re(t.onMouseDown,p=>{!s&&p.button===0&&p.ctrlKey===!1?c.onValueChange(i):p.preventDefault()}),onKeyDown:Re(t.onKeyDown,p=>{[" ","Enter"].includes(p.key)&&c.onValueChange(i)}),onFocus:Re(t.onFocus,()=>{const p=c.activationMode!=="manual";!A&&!s&&p&&c.onValueChange(i)})})})});o6.displayName=r6;var i6="TabsContent",l6=y.forwardRef((t,a)=>{const{__scopeTabs:o,value:i,forceMount:s,children:u,...c}=t,d=ih(i6,o),v=s6(d.baseId,i),m=u6(d.baseId,i),A=i===d.value,p=y.useRef(A);return y.useEffect(()=>{const C=requestAnimationFrame(()=>p.current=!1);return()=>cancelAnimationFrame(C)},[]),g.jsx(ln,{present:s||A,children:({present:C})=>g.jsx(ke.div,{"data-state":A?"active":"inactive","data-orientation":d.orientation,role:"tabpanel","aria-labelledby":v,hidden:!C,id:m,tabIndex:0,...c,ref:a,style:{...t.style,animationDuration:p.current?"0s":void 0},children:C&&u})})});l6.displayName=i6;function s6(t,a){return`${t}-trigger-${a}`}function u6(t,a){return`${t}-content-${a}`}var RM=t6,TM=a6,MM=o6,DM=l6,OM="vocs_AiCtaDropdown",D1="vocs_AiCtaDropdown_buttonLeft vocs_AiCtaDropdown_button vocs_Button_button",NM="vocs_AiCtaDropdown_buttonRight vocs_AiCtaDropdown_button vocs_Button_button",LM="vocs_AiCtaDropdown_dropdownMenuContent",jM="vocs_AiCtaDropdown_dropdownMenuItem",nf="vocs_Button_button";function c6(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"Check"}),g.jsx("path",{d:"M7.49991 0.877045C3.84222 0.877045 0.877075 3.84219 0.877075 7.49988C0.877075 11.1575 3.84222 14.1227 7.49991 14.1227C11.1576 14.1227 14.1227 11.1575 14.1227 7.49988C14.1227 3.84219 11.1576 0.877045 7.49991 0.877045ZM1.82708 7.49988C1.82708 4.36686 4.36689 1.82704 7.49991 1.82704C10.6329 1.82704 13.1727 4.36686 13.1727 7.49988C13.1727 10.6329 10.6329 13.1727 7.49991 13.1727C4.36689 13.1727 1.82708 10.6329 1.82708 7.49988ZM10.1589 5.53774C10.3178 5.31191 10.2636 5.00001 10.0378 4.84109C9.81194 4.68217 9.50004 4.73642 9.34112 4.96225L6.51977 8.97154L5.35681 7.78706C5.16334 7.59002 4.84677 7.58711 4.64973 7.78058C4.45268 7.97404 4.44978 8.29061 4.64325 8.48765L6.22658 10.1003C6.33054 10.2062 6.47617 10.2604 6.62407 10.2483C6.77197 10.2363 6.90686 10.1591 6.99226 10.0377L10.1589 5.53774Z",fill:"currentColor",fillRule:"evenodd",clipRule:"evenodd"})]})}function f6(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"Copy"}),g.jsx("path",{d:"M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z",fill:"currentColor",fillRule:"evenodd",clipRule:"evenodd"})]})}function FM(){return g.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"100%",height:"100%",viewBox:"0 0 24 24",children:[g.jsx("title",{children:"OpenAI"}),g.jsx("path",{fill:"currentColor",d:"M22.282 9.821a6 6 0 0 0-.516-4.91a6.05 6.05 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a6 6 0 0 0-3.998 2.9a6.05 6.05 0 0 0 .743 7.097a5.98 5.98 0 0 0 .51 4.911a6.05 6.05 0 0 0 6.515 2.9A6 6 0 0 0 13.26 24a6.06 6.06 0 0 0 5.772-4.206a6 6 0 0 0 3.997-2.9a6.06 6.06 0 0 0-.747-7.073M13.26 22.43a4.48 4.48 0 0 1-2.876-1.04l.141-.081l4.779-2.758a.8.8 0 0 0 .392-.681v-6.737l2.02 1.168a.07.07 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494M3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085l4.783 2.759a.77.77 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646M2.34 7.896a4.5 4.5 0 0 1 2.366-1.973V11.6a.77.77 0 0 0 .388.677l5.815 3.354l-2.02 1.168a.08.08 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855l-5.833-3.387L15.119 7.2a.08.08 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667m2.01-3.023l-.141-.085l-4.774-2.782a.78.78 0 0 0-.785 0L9.409 9.23V6.897a.07.07 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135l-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08L8.704 5.46a.8.8 0 0 0-.393.681zm1.097-2.365l2.602-1.5l2.607 1.5v2.999l-2.597 1.5l-2.607-1.5Z"})]})}function kM(){const{content:t}=wr(),{aiCta:a}=Ot(),o=ft(),[i,s]=y.useState(!1);y.useEffect(()=>{if(!i)return;const v=setTimeout(()=>s(!1),1e3);return()=>clearTimeout(v)},[i]);const u=y.useCallback(()=>{s(!0),navigator.clipboard.writeText(t??"")},[t]),[c,d]=y.useState("");return y.useEffect(()=>{const v=window.location.origin+o.pathname;d(typeof a=="object"?a.query({location:v}):`Please research and analyze this page: ${v} so I can ask you questions about it. Once you have read it, prompt me with any questions I have. Do not post content from the page in your response. Any of my follow up questions must reference the site I gave you.`)},[a,o.pathname]),g.jsxs("div",{className:OM,children:[i?g.jsxs("div",{className:me(nf,D1),children:[g.jsx("div",{style:{width:"14px",height:"14px"},children:g.jsx(c6,{})}),"Copied"]}):g.jsxs(qn,{className:me(nf,D1),href:`https://chatgpt.com?hints=search&q=${encodeURIComponent(c)}`,variant:"styleless",children:[g.jsx("div",{style:{width:"14px",height:"14px"},children:g.jsx(FM,{})}),"Ask in ChatGPT"]}),g.jsxs(iM,{children:[g.jsx(lM,{asChild:!0,children:g.jsx("button",{className:me(nf,NM),type:"button",children:g.jsx("div",{style:{width:"14px",height:"14px"},children:g.jsx(R3,{})})})}),g.jsx(sM,{children:g.jsx(uM,{align:"end",className:LM,sideOffset:4,children:g.jsxs(cM,{className:jM,onClick:u,children:[g.jsx("div",{style:{width:"14px",height:"14px"},children:g.jsx(f6,{})}),"Copy page for LLMs"]})})})]})]})}var zM="vocs_Outline",UM="vocs_Outline_nav",PM="vocs_Outline_heading",IM="vocs_Outline_items",HM="vocs_Outline_item",BM="vocs_Outline_link";function d6({minLevel:t=2,maxLevel:a=3,highlightActive:o=!0,onClickItem:i,showTitle:s=!0}={}){const{outlineFooter:u}=Ot(),{showOutline:c,showAiCta:d}=_r(),v=typeof c=="number"?t+c-1:a,m=y.useRef(!0),{pathname:A,hash:p}=ft(),[C,b]=y.useState([]);y.useEffect(()=>{if(typeof window>"u")return;const R=Array.from(document.querySelectorAll(`.${Gy}`));b(R)},[A]);const S=y.useMemo(()=>C?C.map(R=>{const _=R.querySelector(`.${Yy}`);if(!_)return null;const N=_.getBoundingClientRect(),j=_.id,F=Number(R.tagName[1]),O=R.textContent,I=window.scrollY+N.top;return F<t||F>v?null:{id:j,level:F,slugTargetElement:_,text:O,topOffset:I}}).filter(Boolean):[],[C,v,t]),[x,w]=y.useState(p.replace("#",""));y.useEffect(()=>{if(typeof window>"u")return;const R=new IntersectionObserver(([_])=>{if(!m.current)return;const N=_.target.id;if(_.isIntersecting)w(N);else{if(!(_.target.getBoundingClientRect().top>0))return;const O=S.findIndex(re=>re.id===x),I=S[O-1]?.id;w(I)}},{rootMargin:"0px 0px -95% 0px"});for(const _ of S)R.observe(_.slugTargetElement);return()=>R.disconnect()},[x,S]),y.useEffect(()=>{if(typeof window>"u")return;const R=new IntersectionObserver(([_])=>{if(!m.current)return;const N=S[S.length-1]?.id;_.isIntersecting?w(N):x===N&&w(S[S.length-2].id)});return R.observe(document.querySelector("[data-bottom-observer]")),()=>R.disconnect()},[x,S]),y.useEffect(()=>{if(typeof window>"u")return;const R=R_(()=>{if(m.current){if(window.scrollY===0){w(S[0]?.id);return}if(window.scrollY+document.documentElement.clientHeight>=document.documentElement.scrollHeight){w(S[S.length-1]?.id);return}for(let _=0;_<S.length;_++){const N=S[_];if(window.scrollY<N.topOffset){w(S[_-1]?.id);break}}}},100);return window.addEventListener("scroll",R),()=>window.removeEventListener("scroll",R)},[S]);const D=S.length>0;if(!D&&!d)return null;const T=D?S.filter(R=>R.level===t):[];return g.jsxs("aside",{className:zM,children:[d&&g.jsx(kM,{}),D&&g.jsxs("nav",{className:UM,children:[s&&g.jsx("h2",{className:PM,children:"On this page"}),g.jsx(h6,{activeId:o?x:null,items:S,onClickItem:()=>{i?.(),m.current=!1,setTimeout(()=>{m.current=!0},500)},levelItems:T,setActiveId:w})]}),Jr(u)]})}function h6({activeId:t,items:a,levelItems:o,onClickItem:i,setActiveId:s}){return g.jsx("ul",{className:IM,children:o.map(({id:u,level:c,text:d})=>{const v=`#${u}`,m=t===u,A=(()=>{const C=a.findIndex(x=>x.id===u)+1,b=a[C]?.level;if(b<=c)return null;const S=[];for(let x=C;x<a.length;x++){const w=a[x];if(w.level!==b)break;S.push(w)}return S})();return g.jsxs(y.Fragment,{children:[g.jsx("li",{className:HM,children:g.jsx(ci,{"data-active":m,to:v,onClick:()=>{i?.(),s(u)},className:BM,children:d})}),A&&g.jsx(h6,{activeId:t,levelItems:A,items:a,onClickItem:i,setActiveId:s})]},u)})})}var $M="vocs_Popover";ta.Root=bM;ta.Trigger=EM;function ta({children:t,className:a}){return g.jsx(SM,{children:g.jsx(xM,{className:me($M,a),sideOffset:12,children:t})})}var VM="vocs_Sidebar",qM="vocs_Sidebar_backLink",GM="vocs_Sidebar_divider",YM="vocs_Sidebar_navigation",QM="vocs_Sidebar_group",KM="vocs_Sidebar_logo",XM="vocs_Sidebar_logoWrapper",p6="vocs_Sidebar_section",ZM="vocs_Sidebar_level",JM="vocs_Sidebar_levelCollapsed",WM="vocs_Sidebar_levelInset",eD="vocs_Sidebar_footer",tD="vocs_Sidebar_footerContent",nD="vocs_Sidebar_footerCurtain",m6="vocs_Sidebar_items",fl="vocs_Sidebar_item",hu="vocs_Sidebar_disabledItem",aD="vocs_Sidebar_sectionHeader",rD="vocs_Sidebar_sectionHeaderActive",O1="vocs_Sidebar_sectionTitle",oD="vocs_Sidebar_sectionTitleLink",iD="vocs_Sidebar_sectionCollapse",lD="vocs_Sidebar_sectionCollapseActive";function sD(){const[t,a]=y.useState(()=>{if(!(typeof window>"u")){if(localStorage.getItem("vocs.theme")){const o=localStorage.getItem("vocs.theme");if(o)return o}return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}});return y.useEffect(()=>{t&&localStorage.setItem("vocs.theme",t),t==="dark"?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")},[t]),{setTheme:a,theme:t,toggle(){a(o=>o==="light"?"dark":"light")}}}function uD(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"Moon"}),g.jsx("path",{d:"M2.89998 0.499976C2.89998 0.279062 2.72089 0.0999756 2.49998 0.0999756C2.27906 0.0999756 2.09998 0.279062 2.09998 0.499976V1.09998H1.49998C1.27906 1.09998 1.09998 1.27906 1.09998 1.49998C1.09998 1.72089 1.27906 1.89998 1.49998 1.89998H2.09998V2.49998C2.09998 2.72089 2.27906 2.89998 2.49998 2.89998C2.72089 2.89998 2.89998 2.72089 2.89998 2.49998V1.89998H3.49998C3.72089 1.89998 3.89998 1.72089 3.89998 1.49998C3.89998 1.27906 3.72089 1.09998 3.49998 1.09998H2.89998V0.499976ZM5.89998 3.49998C5.89998 3.27906 5.72089 3.09998 5.49998 3.09998C5.27906 3.09998 5.09998 3.27906 5.09998 3.49998V4.09998H4.49998C4.27906 4.09998 4.09998 4.27906 4.09998 4.49998C4.09998 4.72089 4.27906 4.89998 4.49998 4.89998H5.09998V5.49998C5.09998 5.72089 5.27906 5.89998 5.49998 5.89998C5.72089 5.89998 5.89998 5.72089 5.89998 5.49998V4.89998H6.49998C6.72089 4.89998 6.89998 4.72089 6.89998 4.49998C6.89998 4.27906 6.72089 4.09998 6.49998 4.09998H5.89998V3.49998ZM1.89998 6.49998C1.89998 6.27906 1.72089 6.09998 1.49998 6.09998C1.27906 6.09998 1.09998 6.27906 1.09998 6.49998V7.09998H0.499976C0.279062 7.09998 0.0999756 7.27906 0.0999756 7.49998C0.0999756 7.72089 0.279062 7.89998 0.499976 7.89998H1.09998V8.49998C1.09998 8.72089 1.27906 8.89997 1.49998 8.89997C1.72089 8.89997 1.89998 8.72089 1.89998 8.49998V7.89998H2.49998C2.72089 7.89998 2.89998 7.72089 2.89998 7.49998C2.89998 7.27906 2.72089 7.09998 2.49998 7.09998H1.89998V6.49998ZM8.54406 0.98184L8.24618 0.941586C8.03275 0.917676 7.90692 1.1655 8.02936 1.34194C8.17013 1.54479 8.29981 1.75592 8.41754 1.97445C8.91878 2.90485 9.20322 3.96932 9.20322 5.10022C9.20322 8.37201 6.82247 11.0878 3.69887 11.6097C3.45736 11.65 3.20988 11.6772 2.96008 11.6906C2.74563 11.702 2.62729 11.9535 2.77721 12.1072C2.84551 12.1773 2.91535 12.2458 2.98667 12.3128L3.05883 12.3795L3.31883 12.6045L3.50684 12.7532L3.62796 12.8433L3.81491 12.9742L3.99079 13.089C4.11175 13.1651 4.23536 13.2375 4.36157 13.3059L4.62496 13.4412L4.88553 13.5607L5.18837 13.6828L5.43169 13.7686C5.56564 13.8128 5.70149 13.8529 5.83857 13.8885C5.94262 13.9155 6.04767 13.9401 6.15405 13.9622C6.27993 13.9883 6.40713 14.0109 6.53544 14.0298L6.85241 14.0685L7.11934 14.0892C7.24637 14.0965 7.37436 14.1002 7.50322 14.1002C11.1483 14.1002 14.1032 11.1453 14.1032 7.50023C14.1032 7.25044 14.0893 7.00389 14.0623 6.76131L14.0255 6.48407C13.991 6.26083 13.9453 6.04129 13.8891 5.82642C13.8213 5.56709 13.7382 5.31398 13.6409 5.06881L13.5279 4.80132L13.4507 4.63542L13.3766 4.48666C13.2178 4.17773 13.0353 3.88295 12.8312 3.60423L12.6782 3.40352L12.4793 3.16432L12.3157 2.98361L12.1961 2.85951L12.0355 2.70246L11.8134 2.50184L11.4925 2.24191L11.2483 2.06498L10.9562 1.87446L10.6346 1.68894L10.3073 1.52378L10.1938 1.47176L9.95488 1.3706L9.67791 1.2669L9.42566 1.1846L9.10075 1.09489L8.83599 1.03486L8.54406 0.98184ZM10.4032 5.30023C10.4032 4.27588 10.2002 3.29829 9.83244 2.40604C11.7623 3.28995 13.1032 5.23862 13.1032 7.50023C13.1032 10.593 10.596 13.1002 7.50322 13.1002C6.63646 13.1002 5.81597 12.9036 5.08355 12.5522C6.5419 12.0941 7.81081 11.2082 8.74322 10.0416C8.87963 10.2284 9.10028 10.3497 9.34928 10.3497C9.76349 10.3497 10.0993 10.0139 10.0993 9.59971C10.0993 9.24256 9.84965 8.94373 9.51535 8.86816C9.57741 8.75165 9.63653 8.63334 9.6926 8.51332C9.88358 8.63163 10.1088 8.69993 10.35 8.69993C11.0403 8.69993 11.6 8.14028 11.6 7.44993C11.6 6.75976 11.0406 6.20024 10.3505 6.19993C10.3853 5.90487 10.4032 5.60464 10.4032 5.30023Z",fill:"currentColor",fillRule:"evenodd",clipRule:"evenodd"})]})}function cD(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 15 15",fill:"none",children:[g.jsx("title",{children:"Sun"}),g.jsx("path",{d:"M7.5 0C7.77614 0 8 0.223858 8 0.5V2.5C8 2.77614 7.77614 3 7.5 3C7.22386 3 7 2.77614 7 2.5V0.5C7 0.223858 7.22386 0 7.5 0ZM2.1967 2.1967C2.39196 2.00144 2.70854 2.00144 2.90381 2.1967L4.31802 3.61091C4.51328 3.80617 4.51328 4.12276 4.31802 4.31802C4.12276 4.51328 3.80617 4.51328 3.61091 4.31802L2.1967 2.90381C2.00144 2.70854 2.00144 2.39196 2.1967 2.1967ZM0.5 7C0.223858 7 0 7.22386 0 7.5C0 7.77614 0.223858 8 0.5 8H2.5C2.77614 8 3 7.77614 3 7.5C3 7.22386 2.77614 7 2.5 7H0.5ZM2.1967 12.8033C2.00144 12.608 2.00144 12.2915 2.1967 12.0962L3.61091 10.682C3.80617 10.4867 4.12276 10.4867 4.31802 10.682C4.51328 10.8772 4.51328 11.1938 4.31802 11.3891L2.90381 12.8033C2.70854 12.9986 2.39196 12.9986 2.1967 12.8033ZM12.5 7C12.2239 7 12 7.22386 12 7.5C12 7.77614 12.2239 8 12.5 8H14.5C14.7761 8 15 7.77614 15 7.5C15 7.22386 14.7761 7 14.5 7H12.5ZM10.682 4.31802C10.4867 4.12276 10.4867 3.80617 10.682 3.61091L12.0962 2.1967C12.2915 2.00144 12.608 2.00144 12.8033 2.1967C12.9986 2.39196 12.9986 2.70854 12.8033 2.90381L11.3891 4.31802C11.1938 4.51328 10.8772 4.51328 10.682 4.31802ZM8 12.5C8 12.2239 7.77614 12 7.5 12C7.22386 12 7 12.2239 7 12.5V14.5C7 14.7761 7.22386 15 7.5 15C7.77614 15 8 14.7761 8 14.5V12.5ZM10.682 10.682C10.8772 10.4867 11.1938 10.4867 11.3891 10.682L12.8033 12.0962C12.9986 12.2915 12.9986 12.608 12.8033 12.8033C12.608 12.9986 12.2915 12.9986 12.0962 12.8033L10.682 11.3891C10.4867 11.1938 10.4867 10.8772 10.682 10.682ZM5.5 7.5C5.5 6.39543 6.39543 5.5 7.5 5.5C8.60457 5.5 9.5 6.39543 9.5 7.5C9.5 8.60457 8.60457 9.5 7.5 9.5C6.39543 9.5 5.5 8.60457 5.5 7.5ZM7.5 4.5C5.84315 4.5 4.5 5.84315 4.5 7.5C4.5 9.15685 5.84315 10.5 7.5 10.5C9.15685 10.5 10.5 9.15685 10.5 7.5C10.5 5.84315 9.15685 4.5 7.5 4.5Z",fill:"currentColor",fillRule:"evenodd",clipRule:"evenodd"})]})}var fD="vocs_ThemeToggle",N1="vocs_ThemeToggle_themeToggleButton";function v6(){const{theme:t,setTheme:a}=sD();return!Fd()||!t?null:g.jsxs("div",{className:fD,children:[g.jsx("button",{"data-active":t==="light",type:"button",className:N1,onClick:()=>a("light"),children:g.jsx(un,{label:"Light Mode",icon:cD,size:"16px"})}),g.jsx("button",{"data-active":t==="dark",type:"button",className:N1,onClick:()=>a("dark"),children:g.jsx(un,{label:"Dark Mode",icon:uD,size:"16px"})})]})}function g6(t){const{className:a,onClickItem:o}=t,{theme:i}=Ot(),{previousPath:s}=wr(),u=y.useRef(null),c=$u(),[d,v]=y.useState("/");if(y.useEffect(()=>{typeof window>"u"||s&&v(s)},[c.key,c.backLink]),!c)return null;const m=dD(c.items);return g.jsxs("aside",{ref:u,className:me(VM,a),children:[g.jsxs("div",{children:[g.jsxs("div",{className:XM,children:[g.jsx("div",{className:KM,children:g.jsx(ni,{to:"/",style:{alignItems:"center",display:"flex",height:"100%"},children:g.jsx(jd,{})})}),g.jsx("div",{className:GM})]}),g.jsx("nav",{className:YM,children:g.jsxs("div",{className:QM,children:[c.backLink&&g.jsx("section",{className:p6,children:g.jsx("div",{className:m6,children:g.jsxs(ni,{className:me(fl,qM),to:d,children:["←"," ",typeof history<"u"&&history.state?.key&&d!=="/"?"Back":"Home"]})})}),m.map((A,p)=>g.jsx(A6,{depth:0,item:A,onClick:o,sidebarRef:u},`${A.text}${p}`))]})})]}),g.jsxs("div",{className:eD,children:[g.jsx("div",{className:nD}),g.jsxs("div",{className:tD,children:[g.jsx(kd,{}),i?.colorScheme?null:g.jsx(v6,{})]})]})]},c.key)}function dD(t){const a=[];let o=0;for(const i of t){if(i.items){o=a.push(i);continue}a[o]?a[o].items.push(i):a.push({text:"",items:[i]})}return a}function y6(t,a){return t.find(o=>Zr(a,o.link??"")||o.link===a?!0:o.items?y6(o.items,a):!1)}function A6(t){const{depth:a,item:o,onClick:i,sidebarRef:s}=t,u=y.useRef(null),{pathname:c}=ft(),d=PE(o.link||""),v=y.useMemo(()=>o.items?!!y6(o.items,c):!1,[o.items,c]),[m,A]=y.useState(()=>!o.items||v?!1:!!o.collapsed);y.useEffect(()=>{v&&A(!1)},[v]);const p=o.collapsed!==void 0&&o.items!==void 0,C=y.useCallback(x=>{"key"in x&&x.key!=="Enter"||A(w=>!w)},[]),b=y.useCallback(x=>{"key"in x&&x.key!=="Enter"||(x.stopPropagation(),A(w=>!w))},[]),S=y.useRef(!0);return y.useEffect(()=>{!S.current||(S.current=!1,!Zr(c,o.link??""))||requestAnimationFrame(()=>{const w=u.current?.offsetTop??0,D=(s?.current?.clientHeight??0)-120;w<D||s?.current?.scrollTo({top:w-100})})},[o,c,s]),o.items?g.jsxs("section",{ref:u,className:me(p6,a===0&&o.text&&ZM,a===0&&o.text&&m&&JM),children:[o.text&&g.jsxs("div",{className:aD,...p&&!o.link?{role:"button",tabIndex:0,onClick:C,onKeyDown:C}:{},children:[o.text&&(o.link?g.jsx(qn,{"data-active":!!d,onClick:x=>{i?.(x),C(x)},className:me(a===0?[O1,oD]:fl,v&&rD,o.disabled&&hu),href:o.link,variant:"styleless",children:o.text}):g.jsx("div",{className:me(a===0?O1:fl,o.disabled&&hu),children:o.text})),p&&g.jsx("div",{role:"button",tabIndex:0,onClick:b,onKeyDown:b,children:g.jsx(un,{className:me(iD,m&&lD),label:"toggle section",icon:T3,size:"16px"})})]}),!m&&g.jsx("div",{className:me(m6,a!==0&&WM),children:o.items&&o.items.length>0&&a<5&&o.items.map((x,w)=>g.jsx(A6,{depth:a+1,item:x,onClick:i,sidebarRef:s},`${x.text}${w}`))})]}):g.jsx(g.Fragment,{children:o.link?g.jsx(qn,{ref:u,"data-active":!!d,onClick:i,className:me(fl,o.disabled&&hu),href:o.link,variant:"styleless",children:o.text}):g.jsx("div",{className:me(fl,o.disabled&&hu),children:o.text})})}Gf.Curtain=vD;function Gf(){const t=Ot(),{showLogo:a}=_r();return g.jsxs("div",{className:f_,children:[g.jsxs("div",{className:y1,children:[a&&g.jsx("div",{className:Z2,children:g.jsx("div",{className:m_,children:g.jsx(ni,{to:"/",style:{alignItems:"center",display:"flex",height:"100%"},children:g.jsx(jd,{})})})}),t.topNav&&g.jsxs("div",{className:Z2,children:[g.jsx(hD,{items:t.topNav}),g.jsx(mD,{items:t.topNav})]})]}),g.jsx("div",{className:y1,children:g.jsx("div",{className:Z2,style:{marginRight:"-8px"},children:g.jsx(c_,{})})})]})}function hD({items:t}){const{pathname:a}=ft(),o=Rl({pathname:a,items:t});return g.jsx(i3,{className:O3,children:g.jsxs(l3,{children:[t.map((i,s)=>i.element?Jr(i.element):i.link?g.jsx(Ku,{active:o?.includes(i.id),href:i.link,children:i.text},s):g.jsxs(s3,{className:p_,children:[g.jsx(u3,{active:o?.includes(i.id),children:i.text}),g.jsx(c3,{className:d_,children:g.jsx(pD,{items:i.items||[]})})]},s)),g.jsx(gd,{})]})})}function pD({items:t}){const{pathname:a}=ft(),o=Rl({pathname:a,items:t});return g.jsx("ul",{children:t?.map((i,s)=>g.jsx(Ku,{active:o.includes(i.id),href:i.link,children:i.text},s))})}function mD({items:t}){const[a,o]=y.useState(!1),{showSidebar:i}=_r(),{pathname:s}=ft(),u=Rl({pathname:s,items:t}),c=t.filter(A=>A.id===u[0])[0],{basePath:d,theme:v}=Ot(),m=d;return g.jsx("div",{className:me(O3,g_),children:g.jsxs(ta.Root,{modal:!0,open:a,onOpenChange:o,children:[g.jsx(ta.Trigger,{className:me(D3,fu),children:i||c?g.jsxs(g.Fragment,{children:[c?.text??"Menu",g.jsx(un,{label:"Menu",icon:R3,size:"16px"})]}):g.jsx(un,{label:"Menu",icon:M3,size:"16px"})}),g.jsxs(ta,{className:w_,children:[g.jsxs(r_,{type:"single",collapsible:!0,style:{display:"flex",flexDirection:"column"},children:[t.map((A,p)=>A.element?Jr(A.element):A.link?g.jsx(qn,{"data-active":u.includes(A.id),className:fu,href:A.link,onClick:()=>o(!1),variant:"styleless",children:A.text},p):g.jsxs(o_,{value:p.toString(),children:[g.jsx(i_,{className:me(fu,b_),"data-active":u.includes(A.id),style:aa({[A_]:`url(${m}/.vocs/icons/chevron-down.svg)`,[C_]:`url(${m}/.vocs/icons/chevron-up.svg)`}),children:A.text}),g.jsx(l_,{className:y_,children:A.items?.map((C,b)=>g.jsx(qn,{className:fu,href:C.link,onClick:()=>o(!1),variant:"styleless",children:C.text},b))})]},p)),g.jsx(gd,{})]}),g.jsxs("div",{className:__,children:[g.jsx(kd,{}),v?.colorScheme?null:g.jsx(v6,{})]})]})]})})}function vD({enableScrollToTop:t}){const{pathname:a}=ft(),{layout:o,showSidebar:i}=_r(),{frontmatter:s={}}=wr(),u=$u(),[c,d]=y.useState(!1),[v,m]=y.useState(!1),A=y.useMemo(()=>!u||o==="minimal"?void 0:C6({sidebarItems:u.items,pathname:a})?.text,[o,a,u]),p=y.useMemo(()=>{if(!(typeof window>"u"))return document.querySelector(".vocs_Content h1")?.textContent},[]),C=A||s.title||p;return g.jsxs("div",{className:h_,children:[g.jsx("div",{className:v1,children:g.jsx("div",{className:X2,children:i?g.jsxs(ta.Root,{modal:!0,open:v,onOpenChange:m,children:[g.jsxs(ta.Trigger,{className:D3,children:[g.jsx(un,{label:"Menu",icon:M3,size:"13px"}),g.jsx("div",{className:v_,children:C})]}),g.jsx(ta,{className:x_,children:g.jsx(g6,{onClickItem:()=>m(!1)})})]}):C})}),g.jsxs("div",{className:v1,children:[t&&g.jsxs(g.Fragment,{children:[g.jsx("div",{className:X2,children:g.jsxs("button",{className:g1,onClick:()=>window.scrollTo({behavior:"smooth",top:0}),type:"button",children:["Top",g.jsx(un,{label:"Scroll to top",icon:s_,size:"16px"})]})}),g.jsx("div",{className:S_})]}),o==="docs"&&g.jsx("div",{className:X2,children:g.jsxs(ta.Root,{modal:!0,open:c,onOpenChange:d,children:[g.jsxs(ta.Trigger,{className:g1,children:["On this page",g.jsx(un,{label:"On this page",icon:T3,size:"16px"})]}),g.jsx(ta,{className:E_,children:g.jsx(d6,{onClickItem:()=>d(!1),showTitle:!1})})]})})]})]})}function C6({sidebarItems:t,pathname:a}){const o=a.replace(/(.+)\/$/,"$1");for(const i of t){if(i?.link===o)return i;if(i.items){const s=C6({sidebarItems:i.items,pathname:o});if(s)return s}}}var gD="vocs_SkipLink";const b6="vocs-content";function yD(){const{pathname:t}=ft();return g.jsx("a",{className:me(gD,IA),href:`${t}#${b6}`,children:"Skip to content"})}var AD="vocs_DocsLayout",CD="vocs_DocsLayout_content",bD="vocs_DocsLayout_content_withTopNav",ED="vocs_DocsLayout_content_withSidebar",SD="vocs_DocsLayout_gutterLeft",xD="vocs_DocsLayout_gutterTop",wD="vocs_DocsLayout_gutterTop_offsetLeftGutter",_D="vocs_DocsLayout_gutterTop_sticky",RD="vocs_DocsLayout_gutterTopCurtain",TD="vocs_DocsLayout_gutterTopCurtain_hidden",MD="vocs_DocsLayout_gutterTopCurtain_withSidebar",DD="vocs_DocsLayout_gutterRight",OD="vocs_DocsLayout_gutterRight_withSidebar",ND="vocs_DocsLayout_sidebar";function Yf({children:t}){const{banner:a,font:o}=Ot(),{frontmatter:i={}}=wr(),{content:s}=i,{layout:u,showOutline:c,showSidebar:d,showTopNav:v}=_r(),{ref:m,inView:A}=qy({initialInView:!0,rootMargin:"100px 0px 0px 0px"}),[p,C]=PA("banner",!0);return g.jsxs("div",{className:AD,"data-layout":u,style:aa({[p8]:p?a?.height:void 0,[Fg.default]:o?.default?.google?`${o.default.google}, ${jg.default}`:void 0,[Fg.mono]:o?.mono?.google?`${o.mono.google}, ${jg.mono}`:void 0}),children:[g.jsx(yD,{}),p&&g.jsx(k8,{hide:()=>C(!1)}),d&&g.jsx("div",{className:SD,children:g.jsx(g6,{className:ND})}),v&&g.jsxs(g.Fragment,{children:[g.jsxs("div",{ref:m,className:me(xD,d&&wD,(u==="minimal"||u==="landing")&&_D),children:[g.jsx(Uf,{}),g.jsx(Gf,{})]}),g.jsxs("div",{className:me(RD,d&&MD,(u==="minimal"||u==="landing")&&TD),children:[g.jsx(Uf.Curtain,{}),g.jsx(Gf.Curtain,{enableScrollToTop:!A})]})]}),c&&g.jsx("div",{className:me(DD,d&&OD),children:g.jsx(d6,{})}),g.jsxs("div",{id:b6,className:me(CD,d&&ED,v&&bD),style:aa({[L2.horizontalPadding]:s?.horizontalPadding,[L2.width]:s?.width,[L2.verticalPadding]:s?.verticalPadding}),children:[g.jsx(Xy,{children:t}),g.jsx(Pw,{})]}),g.jsx("div",{"data-bottom-observer":!0})]})}const Qf={},E6=gt.createContext(Qf);function LD(t){const a=gt.useContext(E6);return gt.useMemo(function(){return typeof t=="function"?t(a):{...a,...t}},[a,t])}function jD(t){let a;return t.disableParentContext?a=typeof t.components=="function"?t.components(Qf):t.components||Qf:a=LD(t.components),gt.createElement(E6.Provider,{value:a},t.children)}var af="vocs_Anchor",FD="vocs_Autolink";function kD(t){return t.href?g.jsx(ci,{...t,className:me(t.className,FD),to:t.href}):null}function zD(t){const{children:a,href:o}=t,{pathname:i}=ft();return a&&typeof a=="object"&&"props"in a&&a.props["data-autolink-icon"]?g.jsx(kD,{className:me(t.className,af),...t}):o?.match(/^#/)?g.jsx("a",{className:me(t.className,af),...t,href:`${i}${o}`}):g.jsx(qn,{className:me(t.className,af),...t,hideExternalIcon:!0})}var S6="vocs_Callout",x6="vocs_Callout_content",w6="vocs_Callout_icon",UD="vocs_Callout_note",PD="vocs_Callout_info",ID="vocs_Callout_warning",HD="vocs_Callout_danger",BD="vocs_Callout_tip",$D="vocs_Callout_success";const VD=Object.freeze(Object.defineProperty({__proto__:null,content:x6,danger:HD,icon:w6,info:PD,note:UD,root:S6,success:$D,tip:BD,warning:ID},Symbol.toStringTag,{value:"Module"}));function L1(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"Exclamation"}),g.jsx("path",{d:"M8.4449 0.608765C8.0183 -0.107015 6.9817 -0.107015 6.55509 0.608766L0.161178 11.3368C-0.275824 12.07 0.252503 13 1.10608 13H13.8939C14.7475 13 15.2758 12.07 14.8388 11.3368L8.4449 0.608765ZM7.4141 1.12073C7.45288 1.05566 7.54712 1.05566 7.5859 1.12073L13.9798 11.8488C14.0196 11.9154 13.9715 12 13.8939 12H1.10608C1.02849 12 0.980454 11.9154 1.02018 11.8488L7.4141 1.12073ZM6.8269 4.48611C6.81221 4.10423 7.11783 3.78663 7.5 3.78663C7.88217 3.78663 8.18778 4.10423 8.1731 4.48612L8.01921 8.48701C8.00848 8.766 7.7792 8.98664 7.5 8.98664C7.2208 8.98664 6.99151 8.766 6.98078 8.48701L6.8269 4.48611ZM8.24989 10.476C8.24989 10.8902 7.9141 11.226 7.49989 11.226C7.08567 11.226 6.74989 10.8902 6.74989 10.476C6.74989 10.0618 7.08567 9.72599 7.49989 9.72599C7.9141 9.72599 8.24989 10.0618 8.24989 10.476Z",fill:"currentColor",fillRule:"evenodd",clipRule:"evenodd"})]})}function j1(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"Info"}),g.jsx("path",{d:"M7.49991 0.876892C3.84222 0.876892 0.877075 3.84204 0.877075 7.49972C0.877075 11.1574 3.84222 14.1226 7.49991 14.1226C11.1576 14.1226 14.1227 11.1574 14.1227 7.49972C14.1227 3.84204 11.1576 0.876892 7.49991 0.876892ZM1.82707 7.49972C1.82707 4.36671 4.36689 1.82689 7.49991 1.82689C10.6329 1.82689 13.1727 4.36671 13.1727 7.49972C13.1727 10.6327 10.6329 13.1726 7.49991 13.1726C4.36689 13.1726 1.82707 10.6327 1.82707 7.49972ZM8.24992 4.49999C8.24992 4.9142 7.91413 5.24999 7.49992 5.24999C7.08571 5.24999 6.74992 4.9142 6.74992 4.49999C6.74992 4.08577 7.08571 3.74999 7.49992 3.74999C7.91413 3.74999 8.24992 4.08577 8.24992 4.49999ZM6.00003 5.99999H6.50003H7.50003C7.77618 5.99999 8.00003 6.22384 8.00003 6.49999V9.99999H8.50003H9.00003V11H8.50003H7.50003H6.50003H6.00003V9.99999H6.50003H7.00003V6.99999H6.50003H6.00003V5.99999Z",fill:"currentColor",fillRule:"evenodd",clipRule:"evenodd"})]})}function qD(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"Lightning Bolt"}),g.jsx("path",{d:"M8.69667 0.0403541C8.90859 0.131038 9.03106 0.354857 8.99316 0.582235L8.0902 6.00001H12.5C12.6893 6.00001 12.8625 6.10701 12.9472 6.27641C13.0319 6.4458 13.0136 6.6485 12.8999 6.80001L6.89997 14.8C6.76167 14.9844 6.51521 15.0503 6.30328 14.9597C6.09135 14.869 5.96888 14.6452 6.00678 14.4178L6.90974 9H2.49999C2.31061 9 2.13748 8.893 2.05278 8.72361C1.96809 8.55422 1.98636 8.35151 2.09999 8.2L8.09997 0.200038C8.23828 0.0156255 8.48474 -0.0503301 8.69667 0.0403541ZM3.49999 8.00001H7.49997C7.64695 8.00001 7.78648 8.06467 7.88148 8.17682C7.97648 8.28896 8.01733 8.43723 7.99317 8.5822L7.33027 12.5596L11.5 7.00001H7.49997C7.353 7.00001 7.21347 6.93534 7.11846 6.8232C7.02346 6.71105 6.98261 6.56279 7.00678 6.41781L7.66968 2.44042L3.49999 8.00001Z",fill:"currentColor",fillRule:"evenodd",clipRule:"evenodd"})]})}function GD({className:t,children:a,type:o}){return g.jsxs("aside",{className:me(t,S6,VD[o]),children:[g.jsxs("div",{className:w6,children:[o==="note"&&g.jsx(j1,{}),o==="info"&&g.jsx(j1,{}),o==="warning"&&g.jsx(L1,{}),o==="danger"&&g.jsx(L1,{}),o==="tip"&&g.jsx(qD,{}),o==="success"&&g.jsx(c6,{})]}),g.jsx("div",{className:x6,children:a})]})}var YD="vocs_Aside";function QD(t){const a=me(t.className,YD);return"data-callout"in t?g.jsx(GD,{className:a,type:t["data-callout"],children:t.children}):g.jsx("aside",{...t,className:a})}var KD="vocs_Blockquote";function XD(t){return g.jsx("blockquote",{...t,className:me(t.className,KD)})}var ZD="vocs_Code";function JD(t){const a=WD(t.children);return g.jsx("code",{...t,className:me(t.className,ZD),children:a})}function WD(t){return Array.isArray(t)?t.map((a,o)=>a.props&&"data-line"in a.props&&typeof a.props.children=="string"&&a.props.children.trim()===""&&t[o+1]?.props?.className?.includes("twoslash-tag-line")?null:a).filter(Boolean):t}var eO="vocs_Details";function tO(t){return g.jsx("details",{...t,className:me(t.className,eO)})}var nO="vocs_Authors",aO="vocs_Authors_authors",rO="vocs_Authors_link",F1="vocs_Authors_separator";function _6(t){const{frontmatter:a}=wr(),{authors:o=a?.authors,date:i=a?.date}=t,s=y.useMemo(()=>{if(o)return Array.isArray(o)?o:o.split(",").map(c=>c.trim())},[o]),u=y.useMemo(()=>i?new Date(i).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric"}):null,[i]);return g.jsxs("div",{className:nO,children:[u,s&&(u?" by ":"By "),g.jsx("span",{className:aO,children:s?.map((c,d)=>{const{text:v,url:m}=oO(c);return g.jsxs(y.Fragment,{children:[m?g.jsx("a",{className:rO,href:m,target:"_blank",rel:"noopener noreferrer",children:v}):v,d<s.length-2&&g.jsx("span",{className:F1,children:", "}),d<s.length-1&&g.jsx("span",{className:F1,children:" & "})]},d)})})]})}function oO(t){const a=t.match(/\[(.+)\]\((.+)\)/);return a?{text:a[1],url:a[2]}:{text:t,url:void 0}}const k1=[];var iO="vocs_BlogPosts",lO="vocs_BlogPosts_description",sO="vocs_BlogPosts_divider",uO="vocs_BlogPosts_post",cO="vocs_BlogPosts_readMore",fO="vocs_BlogPosts_title";function dO(){return g.jsx("div",{className:iO,children:k1.map((t,a)=>g.jsxs(y.Fragment,{children:[g.jsx("div",{className:uO,children:g.jsxs(ni,{to:t.path,children:[g.jsx("h2",{className:fO,children:t.title}),g.jsx(_6,{authors:t.authors,date:t.date}),g.jsxs("p",{className:lO,children:[t.description," ",g.jsx("span",{className:cO,children:"[→]"})]})]})}),a<k1.length-1&&g.jsx("hr",{className:sO})]},a))})}var hO="var(--vocs_Sponsors_columns)",pO="var(--vocs_Sponsors_height)",mO="vocs_Sponsors",vO="vocs_Sponsors_title",gO="vocs_Sponsors_row",yO="vocs_Sponsors_column",AO="vocs_Sponsors_sponsor",CO="vocs_Sponsors_image";function bO(){const{sponsors:t}=Ot();return g.jsx("div",{className:mO,children:t?.map((a,o)=>g.jsxs(y.Fragment,{children:[g.jsx("div",{className:vO,children:a.name}),a.items.map((i,s)=>g.jsx("div",{className:gO,style:aa({[hO]:i.length.toString(),[pO]:`${a.height?.toString()??"40"}px`}),children:i.map((u,c)=>g.jsx(qn,{className:me(yO,u?AO:void 0),href:u?.link,hideExternalIcon:!0,variant:"styleless",children:u?.image&&g.jsx("img",{className:CO,src:u?.image,alt:u?.name})},c))},s))]},o))})}var EO="var(--vocs_AutolinkIcon_iconUrl)",SO="vocs_AutolinkIcon";function xO(t){const{basePath:a}=Ot(),o=a;return g.jsx("div",{...t,className:me(t.className,SO),style:aa({[EO]:`url(${o}/.vocs/icons/link.svg)`})})}var wO="vocs_Tabs",_O="vocs_Tabs_list",RO="vocs_Tabs_trigger",TO="vocs_Tabs_content";function MO(t){return g.jsx(RM,{...t,className:me(t.className,wO)})}function DO(t){return g.jsx(TM,{...t,className:me(t.className,_O)})}function OO(t){return g.jsx(MM,{...t,className:me(t.className,RO)})}function NO(t){return g.jsx(DM,{...t,className:me(t.className,TO)})}var LO="vocs_CodeGroup";function jO({children:t}){if(!Array.isArray(t))return null;const a=t.map(o=>{const i=o.props["data-title"]?o:o.props.children,{props:s}=i,u=s["data-title"],c=s.children;return{title:u,content:c}});return g.jsxs(MO,{className:LO,defaultValue:a[0].title,children:[g.jsx(DO,{"aria-label":"Code group",children:a.map(({title:o},i)=>g.jsx(OO,{value:o||i.toString(),children:o},o||i.toString()))}),a.map(({title:o,content:i},s)=>{const u=i.props?.children?.props?.className?.includes("shiki");return g.jsx(NO,{"data-shiki":u,value:o||s.toString(),children:i},o||s.toString())})]})}var FO="vocs_Div",kO="vocs_Step",R6="vocs_Step_title",zO="vocs_Step_content",UO="vocs_H2";function T6(t){return g.jsx(fi,{...t,className:me(t.className,UO),level:2})}var PO="vocs_H3";function M6(t){return g.jsx(fi,{...t,className:me(t.className,PO),level:3})}var IO="vocs_H4";function D6(t){return g.jsx(fi,{...t,className:me(t.className,IO),level:4})}var HO="vocs_H5";function O6(t){return g.jsx(fi,{...t,className:me(t.className,HO),level:5})}var BO="vocs_H6";function N6(t){return g.jsx(fi,{...t,className:me(t.className,BO),level:6})}function $O({children:t,className:a,title:o,titleLevel:i=2}){const s=(()=>{if(i===2)return T6;if(i===3)return M6;if(i===4)return D6;if(i===5)return O6;if(i===6)return N6;throw new Error("Invalid.")})();return g.jsxs("div",{className:me(a,kO),children:[typeof o=="string"?g.jsx(s,{className:R6,children:o}):o,g.jsx("div",{className:zO,children:t})]})}var VO="vocs_Steps";function qO({children:t,className:a}){return g.jsx("div",{className:me(a,VO),children:t})}function GO({children:t}){return Array.isArray(t)?g.jsx(qO,{children:t.map(({props:a},o)=>{const[i,...s]=Array.isArray(a.children)?a.children:[a.children];return g.jsx($O,{title:y.cloneElement(i,{className:R6}),children:s},o)})}):null}var YO="vocs_Subtitle";function QO({children:t}){return g.jsx("div",{className:YO,children:t})}function KO(t){const{layout:a}=_r(),o=me(t.className,FO);return t.className==="code-group"?g.jsx(jO,{...t,className:o}):"data-authors"in t?g.jsx(_6,{}):"data-blog-posts"in t?g.jsx(dO,{}):"data-sponsors"in t?g.jsx(bO,{}):"data-autolink-icon"in t&&a==="docs"?g.jsx(xO,{...t,className:o}):"data-vocs-steps"in t?g.jsx(GO,{...t,className:o}):t.role==="doc-subtitle"?g.jsx(QO,{...t}):g.jsx("div",{...t,className:o})}var XO="vocs_Figcaption";function ZO(t){const a=me(t.className,XO);return g.jsx("figcaption",{...t,className:a})}var JO="vocs_Figure";function WO(t){const a=me(t.className,JO);return g.jsx("figure",{...t,className:a})}var eN="vocs_Header";function tN(t){return g.jsx("header",{...t,className:me(t.className,eN)})}var nN="vocs_HorizontalRule";function aN(t){return g.jsx("hr",{...t,className:me(t.className,nN)})}var rN="vocs_List",oN="vocs_List_ordered",iN="vocs_List_unordered";function z1({ordered:t,...a}){const o=t?"ol":"ul";return g.jsx(o,{...a,className:me(a.className,rN,t?oN:iN)})}var lN="vocs_ListItem";function sN(t){return g.jsx("li",{...t,className:me(t.className,lN)})}function uN(){const t=y.useRef(null),[a,o]=y.useState(!1);y.useEffect(()=>{if(!a)return;const s=setTimeout(()=>o(!1),1e3);return()=>clearTimeout(s)},[a]);function i(){o(!0);const s=t.current?.cloneNode(!0),u=s?.querySelectorAll("button,.line.diff.remove,.twoslash-popup-info-hover,.twoslash-popup-info,.twoslash-meta-line,.twoslash-tag-line");for(const c of u??[])c.remove();navigator.clipboard.writeText(s?.textContent)}return{copied:a,copy:i,ref:t}}var cN="vocs_CopyButton",fN="vocs_CopyButton_copied";function dN(){return g.jsxs("svg",{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 68 67",children:[g.jsx("title",{children:"Checkmark"}),g.jsx("path",{fill:"currentColor",d:"M26.175 66.121c1.904 0 3.418-.83 4.492-2.49L66.263 7.332c.83-1.27 1.123-2.295 1.123-3.32 0-2.393-1.563-4.004-4.004-4.004-1.758 0-2.734.586-3.809 2.295L25.98 56.209 8.304 32.381c-1.123-1.514-2.198-2.149-3.809-2.149-2.441 0-4.2 1.71-4.2 4.15 0 1.026.44 2.15 1.27 3.224l19.971 25.927c1.367 1.758 2.734 2.588 4.639 2.588Z"})]})}function hN({copy:t,copied:a}){return g.jsx("button",{className:cN,"data-copied":a,onClick:t,type:"button",children:a?g.jsx(un,{label:"Copied",size:"14px",className:fN,icon:dN}):g.jsx(un,{label:"Copy",size:"18px",icon:f6})})}var pN="vocs_CodeBlock";function mN(t){return g.jsx("div",{...t,className:me(t.className,pN)})}function vN(){return g.jsxs("svg",{width:"100%",height:"100%",viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[g.jsx("title",{children:"File"}),g.jsx("path",{d:"M4.2 1H4.17741H4.1774C3.86936 0.999988 3.60368 0.999978 3.38609 1.02067C3.15576 1.04257 2.92825 1.09113 2.71625 1.22104C2.51442 1.34472 2.34473 1.51442 2.22104 1.71625C2.09113 1.92825 2.04257 2.15576 2.02067 2.38609C1.99998 2.60367 1.99999 2.86935 2 3.17738V3.1774V3.2V11.8V11.8226V11.8226C1.99999 12.1307 1.99998 12.3963 2.02067 12.6139C2.04257 12.8442 2.09113 13.0717 2.22104 13.2837C2.34473 13.4856 2.51442 13.6553 2.71625 13.779C2.92825 13.9089 3.15576 13.9574 3.38609 13.9793C3.60368 14 3.86937 14 4.17741 14H4.2H10.8H10.8226C11.1306 14 11.3963 14 11.6139 13.9793C11.8442 13.9574 12.0717 13.9089 12.2837 13.779C12.4856 13.6553 12.6553 13.4856 12.779 13.2837C12.9089 13.0717 12.9574 12.8442 12.9793 12.6139C13 12.3963 13 12.1306 13 11.8226V11.8V3.2V3.17741C13 2.86936 13 2.60368 12.9793 2.38609C12.9574 2.15576 12.9089 1.92825 12.779 1.71625C12.6553 1.51442 12.4856 1.34472 12.2837 1.22104C12.0717 1.09113 11.8442 1.04257 11.6139 1.02067C11.3963 0.999978 11.1306 0.999988 10.8226 1H10.8H4.2ZM3.23875 2.07368C3.26722 2.05623 3.32362 2.03112 3.48075 2.01618C3.64532 2.00053 3.86298 2 4.2 2H10.8C11.137 2 11.3547 2.00053 11.5193 2.01618C11.6764 2.03112 11.7328 2.05623 11.7613 2.07368C11.8285 2.11491 11.8851 2.17147 11.9263 2.23875C11.9438 2.26722 11.9689 2.32362 11.9838 2.48075C11.9995 2.64532 12 2.86298 12 3.2V11.8C12 12.137 11.9995 12.3547 11.9838 12.5193C11.9689 12.6764 11.9438 12.7328 11.9263 12.7613C11.8851 12.8285 11.8285 12.8851 11.7613 12.9263C11.7328 12.9438 11.6764 12.9689 11.5193 12.9838C11.3547 12.9995 11.137 13 10.8 13H4.2C3.86298 13 3.64532 12.9995 3.48075 12.9838C3.32362 12.9689 3.26722 12.9438 3.23875 12.9263C3.17147 12.8851 3.11491 12.8285 3.07368 12.7613C3.05624 12.7328 3.03112 12.6764 3.01618 12.5193C3.00053 12.3547 3 12.137 3 11.8V3.2C3 2.86298 3.00053 2.64532 3.01618 2.48075C3.03112 2.32362 3.05624 2.26722 3.07368 2.23875C3.11491 2.17147 3.17147 2.11491 3.23875 2.07368ZM5 10C4.72386 10 4.5 10.2239 4.5 10.5C4.5 10.7761 4.72386 11 5 11H8C8.27614 11 8.5 10.7761 8.5 10.5C8.5 10.2239 8.27614 10 8 10H5ZM4.5 7.5C4.5 7.22386 4.72386 7 5 7H10C10.2761 7 10.5 7.22386 10.5 7.5C10.5 7.77614 10.2761 8 10 8H5C4.72386 8 4.5 7.77614 4.5 7.5ZM5 4C4.72386 4 4.5 4.22386 4.5 4.5C4.5 4.77614 4.72386 5 5 5H10C10.2761 5 10.5 4.77614 10.5 4.5C10.5 4.22386 10.2761 4 10 4H5Z",fill:"currentColor",fillRule:"evenodd",clipRule:"evenodd"})]})}function gN(){return g.jsxs("svg",{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 79 95",fill:"none",children:[g.jsx("title",{children:"Terminal"}),g.jsx("path",{fill:"currentColor",d:"M38.281 34.033c0-1.074-.39-2.05-1.22-2.88L6.885 1.171C6.152.39 5.175 0 4.053 0 1.758 0 0 1.709 0 4.004c0 1.074.488 2.1 1.172 2.88l27.295 27.15L1.172 61.181C.488 61.962 0 62.939 0 64.062c0 2.295 1.758 4.004 4.053 4.004 1.123 0 2.1-.39 2.832-1.172l30.176-29.98c.83-.83 1.22-1.807 1.22-2.88Z"}),g.jsx("path",{stroke:"currentColor",strokeLinecap:"round",strokeWidth:"8px",d:"M36 75h55"})]})}var yN="vocs_CodeTitle";function AN({children:t,className:a,language:o,...i}){return g.jsxs("div",{...i,className:me(a,yN),children:[o==="bash"?g.jsx(un,{label:"Terminal",size:"14px",icon:gN,style:{marginTop:3}}):t.match(/\.(.*)$/)?g.jsx(un,{label:"File",size:"14px",icon:vN,style:{marginTop:1}}):null,t]})}var CN="vocs_Pre",bN="vocs_Pre_wrapper";function EN({children:t,className:a,...o}){const{copied:i,copy:s,ref:u}=uN();function c(m){return!m||typeof m!="object"?m:"props"in m?{...m,props:{...m.props,children:Array.isArray(m.props.children)?m.props.children.map(c):c(m.props.children)}}:m}const d=y.useMemo(()=>c(t),[t,c]);return(m=>a?.includes("shiki")?g.jsxs(mN,{children:[o["data-title"]&&g.jsx(AN,{language:o["data-lang"],children:o["data-title"]}),m]}):m)(g.jsx("div",{className:me(bN),children:g.jsxs("pre",{ref:u,...o,className:me(a,CN),children:[g.jsx(hN,{copied:i,copy:s}),d]})}))}var SN="vocs_Footnotes";function xN(t){return g.jsx("section",{...t,className:me(t.className,SN)})}var U1="vocs_Section";function wN(t){return"data-footnotes"in t?g.jsx(xN,{...t,className:me(t.className,U1)}):g.jsx("section",{...t,className:me(t.className,U1)})}var P1="vocs_Span";function _N(t,a){if(!t||!a)return!1;const o=a.getRootNode==null?void 0:a.getRootNode();if(t.contains(a))return!0;if(o&&Fu(o)){let i=a;for(;i;){if(t===i)return!0;i=i.parentNode||i.host}}return!1}function pu(t){return t?.ownerDocument||document}function Kf(t,a){const o=["mouse","pen"];return o.push("",void 0),o.includes(t)}var RN=typeof document<"u",TN=function(){},to=RN?y.useLayoutEffect:TN;const MN={...li};function mu(t){const a=y.useRef(t);return to(()=>{a.current=t}),a}const DN=MN.useInsertionEffect,ON=DN||(t=>t());function dl(t){const a=y.useRef(()=>{});return ON(()=>{a.current=t}),y.useCallback(function(){for(var o=arguments.length,i=new Array(o),s=0;s<o;s++)i[s]=arguments[s];return a.current==null?void 0:a.current(...i)},[])}const NN="data-floating-ui-focusable",I1="active",H1="selected",LN={...li};let B1=!1,jN=0;const $1=()=>"floating-ui-"+Math.random().toString(36).slice(2,6)+jN++;function FN(){const[t,a]=y.useState(()=>B1?$1():void 0);return to(()=>{t==null&&a($1())},[]),y.useEffect(()=>{B1=!0},[]),t}const kN=LN.useId,L6=kN||FN,zN=y.forwardRef(function(a,o){const{context:{placement:i,elements:{floating:s},middlewareData:{arrow:u,shift:c}},width:d=14,height:v=7,tipRadius:m=0,strokeWidth:A=0,staticOffset:p,stroke:C,d:b,style:{transform:S,...x}={},...w}=a,D=L6(),[T,R]=y.useState(!1);if(to(()=>{if(!s)return;Yn(s).direction==="rtl"&&R(!0)},[s]),!s)return null;const[_,N]=i.split("-"),j=_==="top"||_==="bottom";let F=p;(j&&c!=null&&c.x||!j&&c!=null&&c.y)&&(F=null);const O=A*2,I=O/2,re=d/2*(m/-8+1),pe=v/2*m/4,ce=!!b,de=F&&N==="end"?"bottom":"top";let J=F&&N==="end"?"right":"left";F&&T&&(J=N==="end"?"left":"right");const fe=u?.x!=null?F||u.x:"",U=u?.y!=null?F||u.y:"",H=b||"M0,0"+(" H"+d)+(" L"+(d-re)+","+(v-pe))+(" Q"+d/2+","+v+" "+re+","+(v-pe))+" Z",K={top:ce?"rotate(180deg)":"",left:ce?"rotate(90deg)":"rotate(-90deg)",bottom:ce?"":"rotate(180deg)",right:ce?"rotate(-90deg)":"rotate(90deg)"}[_];return g.jsxs("svg",{...w,"aria-hidden":!0,ref:o,width:ce?d:d+O,height:d,viewBox:"0 0 "+d+" "+(v>d?v:d),style:{position:"absolute",pointerEvents:"none",[J]:fe,[de]:U,[_]:j||ce?"100%":"calc(100% - "+O/2+"px)",transform:[K,S].filter(G=>!!G).join(" "),...x},children:[O>0&&g.jsx("path",{clipPath:"url(#"+D+")",fill:"none",stroke:C,strokeWidth:O+(b?0:1),d:H}),g.jsx("path",{stroke:O&&!b?w.fill:"none",d:H}),g.jsx("clipPath",{id:D,children:g.jsx("rect",{x:-I,y:I*(ce?-1:1),width:d+O,height:d})})]})});function UN(){const t=new Map;return{emit(a,o){var i;(i=t.get(a))==null||i.forEach(s=>s(o))},on(a,o){t.has(a)||t.set(a,new Set),t.get(a).add(o)},off(a,o){var i;(i=t.get(a))==null||i.delete(o)}}}const PN=y.createContext(null),IN=y.createContext(null),j6=()=>{var t;return((t=y.useContext(PN))==null?void 0:t.id)||null},F6=()=>y.useContext(IN);function HN(t){return"data-floating-ui-"+t}function _n(t){t.current!==-1&&(clearTimeout(t.current),t.current=-1)}const V1=HN("safe-polygon");function rf(t,a,o){if(o&&!Kf(o))return 0;if(typeof t=="number")return t;if(typeof t=="function"){const i=t();return typeof i=="number"?i:i?.[a]}return t?.[a]}function of(t){return typeof t=="function"?t():t}function BN(t,a){a===void 0&&(a={});const{open:o,onOpenChange:i,dataRef:s,events:u,elements:c}=t,{enabled:d=!0,delay:v=0,handleClose:m=null,mouseOnly:A=!1,restMs:p=0,move:C=!0}=a,b=F6(),S=j6(),x=mu(m),w=mu(v),D=mu(o),T=mu(p),R=y.useRef(),_=y.useRef(-1),N=y.useRef(),j=y.useRef(-1),F=y.useRef(!0),O=y.useRef(!1),I=y.useRef(()=>{}),re=y.useRef(!1),pe=dl(()=>{var H;const K=(H=s.current.openEvent)==null?void 0:H.type;return K?.includes("mouse")&&K!=="mousedown"});y.useEffect(()=>{if(!d)return;function H(K){let{open:G}=K;G||(_n(_),_n(j),F.current=!0,re.current=!1)}return u.on("openchange",H),()=>{u.off("openchange",H)}},[d,u]),y.useEffect(()=>{if(!d||!x.current||!o)return;function H(G){pe()&&i(!1,G,"hover")}const K=pu(c.floating).documentElement;return K.addEventListener("mouseleave",H),()=>{K.removeEventListener("mouseleave",H)}},[c.floating,o,i,d,x,pe]);const ce=y.useCallback(function(H,K,G){K===void 0&&(K=!0),G===void 0&&(G="hover");const se=rf(w.current,"close",R.current);se&&!N.current?(_n(_),_.current=window.setTimeout(()=>i(!1,H,G),se)):K&&(_n(_),i(!1,H,G))},[w,i]),de=dl(()=>{I.current(),N.current=void 0}),J=dl(()=>{if(O.current){const H=pu(c.floating).body;H.style.pointerEvents="",H.removeAttribute(V1),O.current=!1}}),fe=dl(()=>s.current.openEvent?["click","mousedown"].includes(s.current.openEvent.type):!1);y.useEffect(()=>{if(!d)return;function H($){if(_n(_),F.current=!1,A&&!Kf(R.current)||of(T.current)>0&&!rf(w.current,"open"))return;const ne=rf(w.current,"open",R.current);ne?_.current=window.setTimeout(()=>{D.current||i(!0,$,"hover")},ne):o||i(!0,$,"hover")}function K($){if(fe()){J();return}I.current();const ne=pu(c.floating);if(_n(j),re.current=!1,x.current&&s.current.floatingContext){o||_n(_),N.current=x.current({...s.current.floatingContext,tree:b,x:$.clientX,y:$.clientY,onClose(){J(),de(),fe()||ce($,!0,"safe-polygon")}});const Ae=N.current;ne.addEventListener("mousemove",Ae),I.current=()=>{ne.removeEventListener("mousemove",Ae)};return}(R.current!=="touch"||!_N(c.floating,$.relatedTarget))&&ce($)}function G($){fe()||s.current.floatingContext&&(x.current==null||x.current({...s.current.floatingContext,tree:b,x:$.clientX,y:$.clientY,onClose(){J(),de(),fe()||ce($)}})($))}function se(){_n(_)}function L($){fe()||ce($,!1)}if(Qt(c.domReference)){const $=c.domReference,ne=c.floating;return o&&$.addEventListener("mouseleave",G),C&&$.addEventListener("mousemove",H,{once:!0}),$.addEventListener("mouseenter",H),$.addEventListener("mouseleave",K),ne&&(ne.addEventListener("mouseleave",G),ne.addEventListener("mouseenter",se),ne.addEventListener("mouseleave",L)),()=>{o&&$.removeEventListener("mouseleave",G),C&&$.removeEventListener("mousemove",H),$.removeEventListener("mouseenter",H),$.removeEventListener("mouseleave",K),ne&&(ne.removeEventListener("mouseleave",G),ne.removeEventListener("mouseenter",se),ne.removeEventListener("mouseleave",L))}}},[c,d,t,A,C,ce,de,J,i,o,D,b,w,x,s,fe,T]),to(()=>{var H;if(d&&o&&(H=x.current)!=null&&(H=H.__options)!=null&&H.blockPointerEvents&&pe()){O.current=!0;const G=c.floating;if(Qt(c.domReference)&&G){var K;const se=pu(c.floating).body;se.setAttribute(V1,"");const L=c.domReference,$=b==null||(K=b.nodesRef.current.find(ne=>ne.id===S))==null||(K=K.context)==null?void 0:K.elements.floating;return $&&($.style.pointerEvents=""),se.style.pointerEvents="none",L.style.pointerEvents="auto",G.style.pointerEvents="auto",()=>{se.style.pointerEvents="",L.style.pointerEvents="",G.style.pointerEvents=""}}}},[d,o,S,c,b,x,pe]),to(()=>{o||(R.current=void 0,re.current=!1,de(),J())},[o,de,J]),y.useEffect(()=>()=>{de(),_n(_),_n(j),J()},[d,c.domReference,de,J]);const U=y.useMemo(()=>{function H(K){R.current=K.pointerType}return{onPointerDown:H,onPointerEnter:H,onMouseMove(K){const{nativeEvent:G}=K;function se(){!F.current&&!D.current&&i(!0,G,"hover")}A&&!Kf(R.current)||o||of(T.current)===0||re.current&&K.movementX**2+K.movementY**2<2||(_n(j),R.current==="touch"?se():(re.current=!0,j.current=window.setTimeout(se,of(T.current))))}}},[A,i,o,D,T]);return y.useMemo(()=>d?{reference:U}:{},[d,U])}function lf(t,a){if(!t||!a)return!1;const o=a.getRootNode==null?void 0:a.getRootNode();if(t.contains(a))return!0;if(o&&Fu(o)){let i=a;for(;i;){if(t===i)return!0;i=i.parentNode||i.host}}return!1}function $N(t){return"composedPath"in t?t.composedPath()[0]:t.target}function VN(t){const{open:a=!1,onOpenChange:o,elements:i}=t,s=L6(),u=y.useRef({}),[c]=y.useState(()=>UN()),d=j6()!=null,[v,m]=y.useState(i.reference),A=dl((b,S,x)=>{u.current.openEvent=b?S:void 0,c.emit("openchange",{open:b,event:S,reason:x,nested:d}),o?.(b,S,x)}),p=y.useMemo(()=>({setPositionReference:m}),[]),C=y.useMemo(()=>({reference:v||i.reference||null,floating:i.floating||null,domReference:i.reference}),[v,i.reference,i.floating]);return y.useMemo(()=>({dataRef:u,open:a,onOpenChange:A,elements:C,events:c,floatingId:s,refs:p}),[a,A,C,c,s,p])}function qN(t){t===void 0&&(t={});const{nodeId:a}=t,o=VN({...t,elements:{reference:null,floating:null,...t.elements}}),i=t.rootContext||o,s=i.elements,[u,c]=y.useState(null),[d,v]=y.useState(null),A=s?.domReference||u,p=y.useRef(null),C=F6();to(()=>{A&&(p.current=A)},[A]);const b=$3({...t,elements:{...s,...d&&{reference:d}}}),S=y.useCallback(R=>{const _=Qt(R)?{getBoundingClientRect:()=>R.getBoundingClientRect(),getClientRects:()=>R.getClientRects(),contextElement:R}:R;v(_),b.refs.setReference(_)},[b.refs]),x=y.useCallback(R=>{(Qt(R)||R===null)&&(p.current=R,c(R)),(Qt(b.refs.reference.current)||b.refs.reference.current===null||R!==null&&!Qt(R))&&b.refs.setReference(R)},[b.refs]),w=y.useMemo(()=>({...b.refs,setReference:x,setPositionReference:S,domReference:p}),[b.refs,x,S]),D=y.useMemo(()=>({...b.elements,domReference:A}),[b.elements,A]),T=y.useMemo(()=>({...b,...i,refs:w,elements:D,nodeId:a}),[b,w,D,a,i]);return to(()=>{i.dataRef.current.floatingContext=T;const R=C?.nodesRef.current.find(_=>_.id===a);R&&(R.context=T)}),y.useMemo(()=>({...b,context:T,refs:w,elements:D}),[b,w,D,T])}function sf(t,a,o){const i=new Map,s=o==="item";let u=t;if(s&&t){const{[I1]:c,[H1]:d,...v}=t;u=v}return{...o==="floating"&&{tabIndex:-1,[NN]:""},...u,...a.map(c=>{const d=c?c[o]:null;return typeof d=="function"?t?d(t):null:d}).concat(t).reduce((c,d)=>(d&&Object.entries(d).forEach(v=>{let[m,A]=v;if(!(s&&[I1,H1].includes(m)))if(m.indexOf("on")===0){if(i.has(m)||i.set(m,[]),typeof A=="function"){var p;(p=i.get(m))==null||p.push(A),c[m]=function(){for(var C,b=arguments.length,S=new Array(b),x=0;x<b;x++)S[x]=arguments[x];return(C=i.get(m))==null?void 0:C.map(w=>w(...S)).find(w=>w!==void 0)}}}else c[m]=A}),c),{})}}function GN(t){t===void 0&&(t=[]);const a=t.map(d=>d?.reference),o=t.map(d=>d?.floating),i=t.map(d=>d?.item),s=y.useCallback(d=>sf(d,t,"reference"),a),u=y.useCallback(d=>sf(d,t,"floating"),o),c=y.useCallback(d=>sf(d,t,"item"),i);return y.useMemo(()=>({getReferenceProps:s,getFloatingProps:u,getItemProps:c}),[s,u,c])}function k6(t,a,o){return o===void 0&&(o=!0),t.filter(s=>{var u;return s.parentId===a&&(!o||((u=s.context)==null?void 0:u.open))}).flatMap(s=>[s,...k6(t,s.id,o)])}function q1(t,a){const[o,i]=t;let s=!1;const u=a.length;for(let c=0,d=u-1;c<u;d=c++){const[v,m]=a[c]||[0,0],[A,p]=a[d]||[0,0];m>=i!=p>=i&&o<=(A-v)*(i-m)/(p-m)+v&&(s=!s)}return s}function YN(t,a){return t[0]>=a.x&&t[0]<=a.x+a.width&&t[1]>=a.y&&t[1]<=a.y+a.height}function QN(t){t===void 0&&(t={});const{buffer:a=.5,blockPointerEvents:o=!1,requireIntent:i=!0}=t,s={current:-1};let u=!1,c=null,d=null,v=typeof performance<"u"?performance.now():0;function m(p,C){const b=performance.now(),S=b-v;if(c===null||d===null||S===0)return c=p,d=C,v=b,null;const x=p-c,w=C-d,T=Math.sqrt(x*x+w*w)/S;return c=p,d=C,v=b,T}const A=p=>{let{x:C,y:b,placement:S,elements:x,onClose:w,nodeId:D,tree:T}=p;return function(_){function N(){_n(s),w()}if(_n(s),!x.domReference||!x.floating||S==null||C==null||b==null)return;const{clientX:j,clientY:F}=_,O=[j,F],I=$N(_),re=_.type==="mouseleave",pe=lf(x.floating,I),ce=lf(x.domReference,I),de=x.domReference.getBoundingClientRect(),J=x.floating.getBoundingClientRect(),fe=S.split("-")[0],U=C>J.right-J.width/2,H=b>J.bottom-J.height/2,K=YN(O,de),G=J.width>de.width,se=J.height>de.height,L=(G?de:J).left,$=(G?de:J).right,ne=(se?de:J).top,ie=(se?de:J).bottom;if(pe&&(u=!0,!re))return;if(ce&&(u=!1),ce&&!re){u=!0;return}if(re&&Qt(_.relatedTarget)&&lf(x.floating,_.relatedTarget)||T&&k6(T.nodesRef.current,D).length)return;if(fe==="top"&&b>=de.bottom-1||fe==="bottom"&&b<=de.top+1||fe==="left"&&C>=de.right-1||fe==="right"&&C<=de.left+1)return N();let Ae=[];switch(fe){case"top":Ae=[[L,de.top+1],[L,J.bottom-1],[$,J.bottom-1],[$,de.top+1]];break;case"bottom":Ae=[[L,J.top+1],[L,de.bottom-1],[$,de.bottom-1],[$,J.top+1]];break;case"left":Ae=[[J.right-1,ie],[J.right-1,ne],[de.left+1,ne],[de.left+1,ie]];break;case"right":Ae=[[de.right-1,ie],[de.right-1,ne],[J.left+1,ne],[J.left+1,ie]];break}function Se(ue){let[q,we]=ue;switch(fe){case"top":{const lt=[G?q+a/2:U?q+a*4:q-a*4,we+a+1],Xe=[G?q-a/2:U?q+a*4:q-a*4,we+a+1],W=[[J.left,U||G?J.bottom-a:J.top],[J.right,U?G?J.bottom-a:J.top:J.bottom-a]];return[lt,Xe,...W]}case"bottom":{const lt=[G?q+a/2:U?q+a*4:q-a*4,we-a],Xe=[G?q-a/2:U?q+a*4:q-a*4,we-a],W=[[J.left,U||G?J.top+a:J.bottom],[J.right,U?G?J.top+a:J.bottom:J.top+a]];return[lt,Xe,...W]}case"left":{const lt=[q+a+1,se?we+a/2:H?we+a*4:we-a*4],Xe=[q+a+1,se?we-a/2:H?we+a*4:we-a*4];return[...[[H||se?J.right-a:J.left,J.top],[H?se?J.right-a:J.left:J.right-a,J.bottom]],lt,Xe]}case"right":{const lt=[q-a,se?we+a/2:H?we+a*4:we-a*4],Xe=[q-a,se?we-a/2:H?we+a*4:we-a*4],W=[[H||se?J.left+a:J.right,J.top],[H?se?J.left+a:J.right:J.left+a,J.bottom]];return[lt,Xe,...W]}}}if(!q1([j,F],Ae)){if(u&&!K)return N();if(!re&&i){const ue=m(_.clientX,_.clientY);if(ue!==null&&ue<.1)return N()}q1([j,F],Se([C,b]))?!u&&i&&(s.current=window.setTimeout(N,40)):N()}}};return A.__options={blockPointerEvents:o},A}function KN({children:t,...a}){const[o,i]=t,s=y.useRef(null),[u,c]=y.useState(!1),{context:d,refs:v,floatingStyles:m}=qN({middleware:[G3({element:s}),V3(8),q3()],open:u,onOpenChange:c,placement:"bottom-start"}),A=BN(d,{handleClose:QN()}),{getReferenceProps:p,getFloatingProps:C}=GN([A]),b=i.props.children,S=o.props.children;return g.jsxs("span",{...a,children:[g.jsx("span",{className:"twoslash-target",ref:v.setReference,...p(),children:b}),u&&g.jsxs("div",{className:"twoslash-popup-info-hover",ref:v.setFloating,style:m,...C(),children:[g.jsx(zN,{ref:s,context:d,fill:_f.background5,height:3,stroke:_f.border2,strokeWidth:1,width:7}),g.jsx("div",{className:"twoslash-popup-scroll-container",children:S})]})]})}function XN(t){const a=me(t.className,P1);return t.className?.includes("twoslash-hover")?g.jsx(KN,{...t,className:a}):g.jsx("span",{...t,className:me(t.className,P1)})}var ZN="vocs_Strong";function JN(t){return g.jsx("strong",{...t,className:me(t.className,ZN)})}var WN="vocs_Summary";function eL(t){return g.jsx("summary",{...t,className:me(t.className,WN)})}var tL="vocs_Table";function nL(t){return g.jsx("table",{...t,className:me(t.className,tL)})}var aL="vocs_TableCell";function rL(t){return g.jsx("td",{...t,className:me(t.className,aL)})}var oL="vocs_TableHeader";function iL(t){return g.jsx("th",{...t,className:me(t.className,oL)})}var lL="vocs_TableRow";function sL(t){return g.jsx("tr",{...t,className:me(t.className,lL)})}const uL={a:zD,aside:QD,blockquote:XD,code:JD,details:tO,div:KO,pre:EN,header:tN,figcaption:ZO,figure:WO,h1:Qy,h2:T6,h3:M6,h4:D6,h5:O6,h6:N6,hr:aN,kd:HA,li:sN,ol:t=>g.jsx(z1,{ordered:!0,...t}),p:Ky,section:wN,span:XN,strong:JN,summary:eL,table:nL,td:rL,th:iL,tr:sL,ul:t=>g.jsx(z1,{ordered:!1,...t})};var uf={},cf,G1;function cc(){if(G1)return cf;G1=1;const t="\\\\/",a=`[^${t}]`,o=0,i="\\.",s="\\+",u="\\?",c="\\/",d="(?=.)",v="[^/]",m=`(?:${c}|$)`,A=`(?:^|${c})`,p=`${i}{1,2}${m}`,C=`(?!${i})`,b=`(?!${A}${p})`,S=`(?!${i}{0,1}${m})`,x=`(?!${p})`,w=`[^.${c}]`,D=`${v}*?`,R={DOT_LITERAL:i,PLUS_LITERAL:s,QMARK_LITERAL:u,SLASH_LITERAL:c,ONE_CHAR:d,QMARK:v,END_ANCHOR:m,DOTS_SLASH:p,NO_DOT:C,NO_DOTS:b,NO_DOT_SLASH:S,NO_DOTS_SLASH:x,QMARK_NO_DOT:w,STAR:D,START_ANCHOR:A,SEP:"/"},_={...R,SLASH_LITERAL:`[${t}]`,QMARK:a,STAR:`${a}*?`,DOTS_SLASH:`${i}{1,2}(?:[${t}]|$)`,NO_DOT:`(?!${i})`,NO_DOTS:`(?!(?:^|[${t}])${i}{1,2}(?:[${t}]|$))`,NO_DOT_SLASH:`(?!${i}{0,1}(?:[${t}]|$))`,NO_DOTS_SLASH:`(?!${i}{1,2}(?:[${t}]|$))`,QMARK_NO_DOT:`[^.${t}]`,START_ANCHOR:`(?:^|[${t}])`,END_ANCHOR:`(?:[${t}]|$)`,SEP:"\\"},N={__proto__:null,alnum:"a-zA-Z0-9",alpha:"a-zA-Z",ascii:"\\x00-\\x7F",blank:" \\t",cntrl:"\\x00-\\x1F\\x7F",digit:"0-9",graph:"\\x21-\\x7E",lower:"a-z",print:"\\x20-\\x7E ",punct:"\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~",space:" \\t\\r\\n\\v\\f",upper:"A-Z",word:"A-Za-z0-9_",xdigit:"A-Fa-f0-9"};return cf={DEFAULT_MAX_EXTGLOB_RECURSION:o,MAX_LENGTH:1024*64,POSIX_REGEX_SOURCE:N,REGEX_BACKSLASH:/\\(?![*+?^${}(|)[\]])/g,REGEX_NON_SPECIAL_CHARS:/^[^@![\].,$*+?^{}()|\\/]+/,REGEX_SPECIAL_CHARS:/[-*+?.^${}(|)[\]]/,REGEX_SPECIAL_CHARS_BACKREF:/(\\?)((\W)(\3*))/g,REGEX_SPECIAL_CHARS_GLOBAL:/([-*+?.^${}(|)[\]])/g,REGEX_REMOVE_BACKSLASH:/(?:\[.*?[^\\]\]|\\(?=.))/g,REPLACEMENTS:{__proto__:null,"***":"*","**/**":"**","**/**/**":"**"},CHAR_0:48,CHAR_9:57,CHAR_UPPERCASE_A:65,CHAR_LOWERCASE_A:97,CHAR_UPPERCASE_Z:90,CHAR_LOWERCASE_Z:122,CHAR_LEFT_PARENTHESES:40,CHAR_RIGHT_PARENTHESES:41,CHAR_ASTERISK:42,CHAR_AMPERSAND:38,CHAR_AT:64,CHAR_BACKWARD_SLASH:92,CHAR_CARRIAGE_RETURN:13,CHAR_CIRCUMFLEX_ACCENT:94,CHAR_COLON:58,CHAR_COMMA:44,CHAR_DOT:46,CHAR_DOUBLE_QUOTE:34,CHAR_EQUAL:61,CHAR_EXCLAMATION_MARK:33,CHAR_FORM_FEED:12,CHAR_FORWARD_SLASH:47,CHAR_GRAVE_ACCENT:96,CHAR_HASH:35,CHAR_HYPHEN_MINUS:45,CHAR_LEFT_ANGLE_BRACKET:60,CHAR_LEFT_CURLY_BRACE:123,CHAR_LEFT_SQUARE_BRACKET:91,CHAR_LINE_FEED:10,CHAR_NO_BREAK_SPACE:160,CHAR_PERCENT:37,CHAR_PLUS:43,CHAR_QUESTION_MARK:63,CHAR_RIGHT_ANGLE_BRACKET:62,CHAR_RIGHT_CURLY_BRACE:125,CHAR_RIGHT_SQUARE_BRACKET:93,CHAR_SEMICOLON:59,CHAR_SINGLE_QUOTE:39,CHAR_SPACE:32,CHAR_TAB:9,CHAR_UNDERSCORE:95,CHAR_VERTICAL_LINE:124,CHAR_ZERO_WIDTH_NOBREAK_SPACE:65279,extglobChars(j){return{"!":{type:"negate",open:"(?:(?!(?:",close:`))${j.STAR})`},"?":{type:"qmark",open:"(?:",close:")?"},"+":{type:"plus",open:"(?:",close:")+"},"*":{type:"star",open:"(?:",close:")*"},"@":{type:"at",open:"(?:",close:")"}}},globChars(j){return j===!0?_:R}},cf}var Y1;function fc(){return Y1||(Y1=1,(function(t){const{REGEX_BACKSLASH:a,REGEX_REMOVE_BACKSLASH:o,REGEX_SPECIAL_CHARS:i,REGEX_SPECIAL_CHARS_GLOBAL:s}=cc();t.isObject=u=>u!==null&&typeof u=="object"&&!Array.isArray(u),t.hasRegexChars=u=>i.test(u),t.isRegexChar=u=>u.length===1&&t.hasRegexChars(u),t.escapeRegex=u=>u.replace(s,"\\$1"),t.toPosixSlashes=u=>u.replace(a,"/"),t.isWindows=()=>{if(typeof navigator<"u"&&navigator.platform){const u=navigator.platform.toLowerCase();return u==="win32"||u==="windows"}return typeof process<"u"&&process.platform?process.platform==="win32":!1},t.removeBackslashes=u=>u.replace(o,c=>c==="\\"?"":c),t.escapeLast=(u,c,d)=>{const v=u.lastIndexOf(c,d);return v===-1?u:u[v-1]==="\\"?t.escapeLast(u,c,v-1):`${u.slice(0,v)}\\${u.slice(v)}`},t.removePrefix=(u,c={})=>{let d=u;return d.startsWith("./")&&(d=d.slice(2),c.prefix="./"),d},t.wrapOutput=(u,c={},d={})=>{const v=d.contains?"":"^",m=d.contains?"":"$";let A=`${v}(?:${u})${m}`;return c.negated===!0&&(A=`(?:^(?!${A}).*$)`),A},t.basename=(u,{windows:c}={})=>{const d=u.split(c?/[\\/]/:"/"),v=d[d.length-1];return v===""?d[d.length-2]:v}})(uf)),uf}var ff,Q1;function cL(){if(Q1)return ff;Q1=1;const t=fc(),{CHAR_ASTERISK:a,CHAR_AT:o,CHAR_BACKWARD_SLASH:i,CHAR_COMMA:s,CHAR_DOT:u,CHAR_EXCLAMATION_MARK:c,CHAR_FORWARD_SLASH:d,CHAR_LEFT_CURLY_BRACE:v,CHAR_LEFT_PARENTHESES:m,CHAR_LEFT_SQUARE_BRACKET:A,CHAR_PLUS:p,CHAR_QUESTION_MARK:C,CHAR_RIGHT_CURLY_BRACE:b,CHAR_RIGHT_PARENTHESES:S,CHAR_RIGHT_SQUARE_BRACKET:x}=cc(),w=R=>R===d||R===i,D=R=>{R.isPrefix!==!0&&(R.depth=R.isGlobstar?1/0:1)};return ff=(R,_)=>{const N=_||{},j=R.length-1,F=N.parts===!0||N.scanToEnd===!0,O=[],I=[],re=[];let pe=R,ce=-1,de=0,J=0,fe=!1,U=!1,H=!1,K=!1,G=!1,se=!1,L=!1,$=!1,ne=!1,ie=!1,Ae=0,Se,ue,q={value:"",depth:0,isGlob:!1};const we=()=>ce>=j,lt=()=>pe.charCodeAt(ce+1),Xe=()=>(Se=ue,pe.charCodeAt(++ce));for(;ce<j;){ue=Xe();let At;if(ue===i){L=q.backslashes=!0,ue=Xe(),ue===v&&(se=!0);continue}if(se===!0||ue===v){for(Ae++;we()!==!0&&(ue=Xe());){if(ue===i){L=q.backslashes=!0,Xe();continue}if(ue===v){Ae++;continue}if(se!==!0&&ue===u&&(ue=Xe())===u){if(fe=q.isBrace=!0,H=q.isGlob=!0,ie=!0,F===!0)continue;break}if(se!==!0&&ue===s){if(fe=q.isBrace=!0,H=q.isGlob=!0,ie=!0,F===!0)continue;break}if(ue===b&&(Ae--,Ae===0)){se=!1,fe=q.isBrace=!0,ie=!0;break}}if(F===!0)continue;break}if(ue===d){if(O.push(ce),I.push(q),q={value:"",depth:0,isGlob:!1},ie===!0)continue;if(Se===u&&ce===de+1){de+=2;continue}J=ce+1;continue}if(N.noext!==!0&&(ue===p||ue===o||ue===a||ue===C||ue===c)===!0&<()===m){if(H=q.isGlob=!0,K=q.isExtglob=!0,ie=!0,ue===c&&ce===de&&(ne=!0),F===!0){for(;we()!==!0&&(ue=Xe());){if(ue===i){L=q.backslashes=!0,ue=Xe();continue}if(ue===S){H=q.isGlob=!0,ie=!0;break}}continue}break}if(ue===a){if(Se===a&&(G=q.isGlobstar=!0),H=q.isGlob=!0,ie=!0,F===!0)continue;break}if(ue===C){if(H=q.isGlob=!0,ie=!0,F===!0)continue;break}if(ue===A){for(;we()!==!0&&(At=Xe());){if(At===i){L=q.backslashes=!0,Xe();continue}if(At===x){U=q.isBracket=!0,H=q.isGlob=!0,ie=!0;break}}if(F===!0)continue;break}if(N.nonegate!==!0&&ue===c&&ce===de){$=q.negated=!0,de++;continue}if(N.noparen!==!0&&ue===m){if(H=q.isGlob=!0,F===!0){for(;we()!==!0&&(ue=Xe());){if(ue===m){L=q.backslashes=!0,ue=Xe();continue}if(ue===S){ie=!0;break}}continue}break}if(H===!0){if(ie=!0,F===!0)continue;break}}N.noext===!0&&(K=!1,H=!1);let W=pe,te="",pt="";de>0&&(te=pe.slice(0,de),pe=pe.slice(de),J-=de),W&&H===!0&&J>0?(W=pe.slice(0,J),pt=pe.slice(J)):H===!0?(W="",pt=pe):W=pe,W&&W!==""&&W!=="/"&&W!==pe&&w(W.charCodeAt(W.length-1))&&(W=W.slice(0,-1)),N.unescape===!0&&(pt&&(pt=t.removeBackslashes(pt)),W&&L===!0&&(W=t.removeBackslashes(W)));const Ze={prefix:te,input:R,start:de,base:W,glob:pt,isBrace:fe,isBracket:U,isGlob:H,isExtglob:K,isGlobstar:G,negated:$,negatedExtglob:ne};if(N.tokens===!0&&(Ze.maxDepth=0,w(ue)||I.push(q),Ze.tokens=I),N.parts===!0||N.tokens===!0){let At;for(let Je=0;Je<O.length;Je++){const en=At?At+1:de,yn=O[Je],On=R.slice(en,yn);N.tokens&&(Je===0&&de!==0?(I[Je].isPrefix=!0,I[Je].value=te):I[Je].value=On,D(I[Je]),Ze.maxDepth+=I[Je].depth),(Je!==0||On!=="")&&re.push(On),At=yn}if(At&&At+1<R.length){const Je=R.slice(At+1);re.push(Je),N.tokens&&(I[I.length-1].value=Je,D(I[I.length-1]),Ze.maxDepth+=I[I.length-1].depth)}Ze.slashes=O,Ze.parts=re}return Ze},ff}var df,K1;function fL(){if(K1)return df;K1=1;const t=cc(),a=fc(),{MAX_LENGTH:o,POSIX_REGEX_SOURCE:i,REGEX_NON_SPECIAL_CHARS:s,REGEX_SPECIAL_CHARS_BACKREF:u,REPLACEMENTS:c}=t,d=(T,R)=>{if(typeof R.expandRange=="function")return R.expandRange(...T,R);T.sort();const _=`[${T.join("-")}]`;try{new RegExp(_)}catch{return T.map(j=>a.escapeRegex(j)).join("..")}return _},v=(T,R)=>`Missing ${T}: "${R}" - use "\\\\${R}" to match literal characters`,m=T=>{const R=[];let _=0,N=0,j=0,F="",O=!1;for(const I of T){if(O===!0){F+=I,O=!1;continue}if(I==="\\"){F+=I,O=!0;continue}if(I==='"'){j=j===1?0:1,F+=I;continue}if(j===0){if(I==="[")_++;else if(I==="]"&&_>0)_--;else if(_===0){if(I==="(")N++;else if(I===")"&&N>0)N--;else if(I==="|"&&N===0){R.push(F),F="";continue}}}F+=I}return R.push(F),R},A=T=>{let R=!1;for(const _ of T){if(R===!0){R=!1;continue}if(_==="\\"){R=!0;continue}if(/[?*+@!()[\]{}]/.test(_))return!1}return!0},p=T=>{let R=T.trim(),_=!0;for(;_===!0;)_=!1,/^@\([^\\()[\]{}|]+\)$/.test(R)&&(R=R.slice(2,-1),_=!0);if(A(R))return R.replace(/\\(.)/g,"$1")},C=T=>{const R=T.map(p).filter(Boolean);for(let _=0;_<R.length;_++)for(let N=_+1;N<R.length;N++){const j=R[_],F=R[N],O=j[0];if(!(!O||j!==O.repeat(j.length)||F!==O.repeat(F.length))&&(j===F||j.startsWith(F)||F.startsWith(j)))return!0}return!1},b=(T,R=!0)=>{if(T[0]!=="+"&&T[0]!=="*"||T[1]!=="(")return;let _=0,N=0,j=0,F=!1;for(let O=1;O<T.length;O++){const I=T[O];if(F===!0){F=!1;continue}if(I==="\\"){F=!0;continue}if(I==='"'){j=j===1?0:1;continue}if(j!==1){if(I==="["){_++;continue}if(I==="]"&&_>0){_--;continue}if(!(_>0)){if(I==="("){N++;continue}if(I===")"&&(N--,N===0))return R===!0&&O!==T.length-1?void 0:{type:T[0],body:T.slice(2,O),end:O}}}}},S=T=>{let R=0;const _=[];for(;R<T.length;){const j=b(T.slice(R),!1);if(!j||j.type!=="*")return;const F=m(j.body).map(I=>I.trim());if(F.length!==1)return;const O=p(F[0]);if(!O||O.length!==1)return;_.push(O),R+=j.end+1}return _.length<1?void 0:`${_.length===1?a.escapeRegex(_[0]):`[${_.map(j=>a.escapeRegex(j)).join("")}]`}*`},x=T=>{let R=0,_=T.trim(),N=b(_);for(;N;)R++,_=N.body.trim(),N=b(_);return R},w=(T,R)=>{if(R.maxExtglobRecursion===!1)return{risky:!1};const _=typeof R.maxExtglobRecursion=="number"?R.maxExtglobRecursion:t.DEFAULT_MAX_EXTGLOB_RECURSION,N=m(T).map(j=>j.trim());if(N.length>1&&(N.some(j=>j==="")||N.some(j=>/^[*?]+$/.test(j))||C(N)))return{risky:!0};for(const j of N){const F=S(j);if(F)return{risky:!0,safeOutput:F};if(x(j)>_)return{risky:!0}}return{risky:!1}},D=(T,R)=>{if(typeof T!="string")throw new TypeError("Expected a string");T=c[T]||T;const _={...R},N=typeof _.maxLength=="number"?Math.min(o,_.maxLength):o;let j=T.length;if(j>N)throw new SyntaxError(`Input length: ${j}, exceeds maximum allowed length: ${N}`);const F={type:"bos",value:"",output:_.prepend||""},O=[F],I=_.capture?"":"?:",re=t.globChars(_.windows),pe=t.extglobChars(re),{DOT_LITERAL:ce,PLUS_LITERAL:de,SLASH_LITERAL:J,ONE_CHAR:fe,DOTS_SLASH:U,NO_DOT:H,NO_DOT_SLASH:K,NO_DOTS_SLASH:G,QMARK:se,QMARK_NO_DOT:L,STAR:$,START_ANCHOR:ne}=re,ie=ye=>`(${I}(?:(?!${ne}${ye.dot?U:ce}).)*?)`,Ae=_.dot?"":H,Se=_.dot?se:L;let ue=_.bash===!0?ie(_):$;_.capture&&(ue=`(${ue})`),typeof _.noext=="boolean"&&(_.noextglob=_.noext);const q={input:T,index:-1,start:0,dot:_.dot===!0,consumed:"",output:"",prefix:"",backtrack:!1,negated:!1,brackets:0,braces:0,parens:0,quotes:0,globstar:!1,tokens:O};T=a.removePrefix(T,q),j=T.length;const we=[],lt=[],Xe=[];let W=F,te;const pt=()=>q.index===j-1,Ze=q.peek=(ye=1)=>T[q.index+ye],At=q.advance=()=>T[++q.index]||"",Je=()=>T.slice(q.index+1),en=(ye="",at=0)=>{q.consumed+=ye,q.index+=at},yn=ye=>{q.output+=ye.output!=null?ye.output:ye.value,en(ye.value)},On=()=>{let ye=1;for(;Ze()==="!"&&(Ze(2)!=="("||Ze(3)==="?");)At(),q.start++,ye++;return ye%2===0?!1:(q.negated=!0,q.start++,!0)},la=ye=>{q[ye]++,Xe.push(ye)},Nn=ye=>{q[ye]--,Xe.pop()},Ue=ye=>{if(W.type==="globstar"){const at=q.braces>0&&(ye.type==="comma"||ye.type==="brace"),ve=ye.extglob===!0||we.length&&(ye.type==="pipe"||ye.type==="paren");ye.type!=="slash"&&ye.type!=="paren"&&!at&&!ve&&(q.output=q.output.slice(0,-W.output.length),W.type="star",W.value="*",W.output=ue,q.output+=W.output)}if(we.length&&ye.type!=="paren"&&(we[we.length-1].inner+=ye.value),(ye.value||ye.output)&&yn(ye),W&&W.type==="text"&&ye.type==="text"){W.output=(W.output||W.value)+ye.value,W.value+=ye.value;return}ye.prev=W,O.push(ye),W=ye},kt=(ye,at)=>{const ve={...pe[at],conditions:1,inner:""};ve.prev=W,ve.parens=q.parens,ve.output=q.output,ve.startIndex=q.index,ve.tokensIndex=O.length;const je=(_.capture?"(":"")+ve.open;la("parens"),Ue({type:ye,value:at,output:q.output?"":fe}),Ue({type:"paren",extglob:!0,value:At(),output:je}),we.push(ve)},Kn=ye=>{const at=T.slice(ye.startIndex,q.index+1),ve=T.slice(ye.startIndex+2,q.index),je=w(ve,_);if((ye.type==="plus"||ye.type==="star")&&je.risky){const rt=je.safeOutput?(ye.output?"":fe)+(_.capture?`(${je.safeOutput})`:je.safeOutput):void 0,zt=O[ye.tokensIndex];zt.type="text",zt.value=at,zt.output=rt||a.escapeRegex(at);for(let mt=ye.tokensIndex+1;mt<O.length;mt++)O[mt].value="",O[mt].output="",delete O[mt].suffix;q.output=ye.output+zt.output,q.backtrack=!0,Ue({type:"paren",extglob:!0,value:te,output:""}),Nn("parens");return}let He=ye.close+(_.capture?")":""),xt;if(ye.type==="negate"){let rt=ue;if(ye.inner&&ye.inner.length>1&&ye.inner.includes("/")&&(rt=ie(_)),(rt!==ue||pt()||/^\)+$/.test(Je()))&&(He=ye.close=`)$))${rt}`),ye.inner.includes("*")&&(xt=Je())&&/^\.[^\\/.]+$/.test(xt)){const zt=D(xt,{...R,fastpaths:!1}).output;He=ye.close=`)${zt})${rt})`}ye.prev.type==="bos"&&(q.negatedExtglob=!0)}Ue({type:"paren",extglob:!0,value:te,output:He}),Nn("parens")};if(_.fastpaths!==!1&&!/(^[*!]|[/()[\]{}"])/.test(T)){let ye=!1,at=T.replace(u,(ve,je,He,xt,rt,zt)=>xt==="\\"?(ye=!0,ve):xt==="?"?je?je+xt+(rt?se.repeat(rt.length):""):zt===0?Se+(rt?se.repeat(rt.length):""):se.repeat(He.length):xt==="."?ce.repeat(He.length):xt==="*"?je?je+xt+(rt?ue:""):ue:je?ve:`\\${ve}`);return ye===!0&&(_.unescape===!0?at=at.replace(/\\/g,""):at=at.replace(/\\+/g,ve=>ve.length%2===0?"\\\\":ve?"\\":"")),at===T&&_.contains===!0?(q.output=T,q):(q.output=a.wrapOutput(at,q,R),q)}for(;!pt();){if(te=At(),te==="\0")continue;if(te==="\\"){const ve=Ze();if(ve==="/"&&_.bash!==!0||ve==="."||ve===";")continue;if(!ve){te+="\\",Ue({type:"text",value:te});continue}const je=/^\\+/.exec(Je());let He=0;if(je&&je[0].length>2&&(He=je[0].length,q.index+=He,He%2!==0&&(te+="\\")),_.unescape===!0?te=At():te+=At(),q.brackets===0){Ue({type:"text",value:te});continue}}if(q.brackets>0&&(te!=="]"||W.value==="["||W.value==="[^")){if(_.posix!==!1&&te===":"){const ve=W.value.slice(1);if(ve.includes("[")&&(W.posix=!0,ve.includes(":"))){const je=W.value.lastIndexOf("["),He=W.value.slice(0,je),xt=W.value.slice(je+2),rt=i[xt];if(rt){W.value=He+rt,q.backtrack=!0,At(),!F.output&&O.indexOf(W)===1&&(F.output=fe);continue}}}(te==="["&&Ze()!==":"||te==="-"&&Ze()==="]")&&(te=`\\${te}`),te==="]"&&(W.value==="["||W.value==="[^")&&(te=`\\${te}`),_.posix===!0&&te==="!"&&W.value==="["&&(te="^"),W.value+=te,yn({value:te});continue}if(q.quotes===1&&te!=='"'){te=a.escapeRegex(te),W.value+=te,yn({value:te});continue}if(te==='"'){q.quotes=q.quotes===1?0:1,_.keepQuotes===!0&&Ue({type:"text",value:te});continue}if(te==="("){la("parens"),Ue({type:"paren",value:te});continue}if(te===")"){if(q.parens===0&&_.strictBrackets===!0)throw new SyntaxError(v("opening","("));const ve=we[we.length-1];if(ve&&q.parens===ve.parens+1){Kn(we.pop());continue}Ue({type:"paren",value:te,output:q.parens?")":"\\)"}),Nn("parens");continue}if(te==="["){if(_.nobracket===!0||!Je().includes("]")){if(_.nobracket!==!0&&_.strictBrackets===!0)throw new SyntaxError(v("closing","]"));te=`\\${te}`}else la("brackets");Ue({type:"bracket",value:te});continue}if(te==="]"){if(_.nobracket===!0||W&&W.type==="bracket"&&W.value.length===1){Ue({type:"text",value:te,output:`\\${te}`});continue}if(q.brackets===0){if(_.strictBrackets===!0)throw new SyntaxError(v("opening","["));Ue({type:"text",value:te,output:`\\${te}`});continue}Nn("brackets");const ve=W.value.slice(1);if(W.posix!==!0&&ve[0]==="^"&&!ve.includes("/")&&(te=`/${te}`),W.value+=te,yn({value:te}),_.literalBrackets===!1||a.hasRegexChars(ve))continue;const je=a.escapeRegex(W.value);if(q.output=q.output.slice(0,-W.value.length),_.literalBrackets===!0){q.output+=je,W.value=je;continue}W.value=`(${I}${je}|${W.value})`,q.output+=W.value;continue}if(te==="{"&&_.nobrace!==!0){la("braces");const ve={type:"brace",value:te,output:"(",outputIndex:q.output.length,tokensIndex:q.tokens.length};lt.push(ve),Ue(ve);continue}if(te==="}"){const ve=lt[lt.length-1];if(_.nobrace===!0||!ve){Ue({type:"text",value:te,output:te});continue}let je=")";if(ve.dots===!0){const He=O.slice(),xt=[];for(let rt=He.length-1;rt>=0&&(O.pop(),He[rt].type!=="brace");rt--)He[rt].type!=="dots"&&xt.unshift(He[rt].value);je=d(xt,_),q.backtrack=!0}if(ve.comma!==!0&&ve.dots!==!0){const He=q.output.slice(0,ve.outputIndex),xt=q.tokens.slice(ve.tokensIndex);ve.value=ve.output="\\{",te=je="\\}",q.output=He;for(const rt of xt)q.output+=rt.output||rt.value}Ue({type:"brace",value:te,output:je}),Nn("braces"),lt.pop();continue}if(te==="|"){we.length>0&&we[we.length-1].conditions++,Ue({type:"text",value:te});continue}if(te===","){let ve=te;const je=lt[lt.length-1];je&&Xe[Xe.length-1]==="braces"&&(je.comma=!0,ve="|"),Ue({type:"comma",value:te,output:ve});continue}if(te==="/"){if(W.type==="dot"&&q.index===q.start+1){q.start=q.index+1,q.consumed="",q.output="",O.pop(),W=F;continue}Ue({type:"slash",value:te,output:J});continue}if(te==="."){if(q.braces>0&&W.type==="dot"){W.value==="."&&(W.output=ce);const ve=lt[lt.length-1];W.type="dots",W.output+=te,W.value+=te,ve.dots=!0;continue}if(q.braces+q.parens===0&&W.type!=="bos"&&W.type!=="slash"){Ue({type:"text",value:te,output:ce});continue}Ue({type:"dot",value:te,output:ce});continue}if(te==="?"){if(!(W&&W.value==="(")&&_.noextglob!==!0&&Ze()==="("&&Ze(2)!=="?"){kt("qmark",te);continue}if(W&&W.type==="paren"){const je=Ze();let He=te;(W.value==="("&&!/[!=<:]/.test(je)||je==="<"&&!/<([!=]|\w+>)/.test(Je()))&&(He=`\\${te}`),Ue({type:"text",value:te,output:He});continue}if(_.dot!==!0&&(W.type==="slash"||W.type==="bos")){Ue({type:"qmark",value:te,output:L});continue}Ue({type:"qmark",value:te,output:se});continue}if(te==="!"){if(_.noextglob!==!0&&Ze()==="("&&(Ze(2)!=="?"||!/[!=<:]/.test(Ze(3)))){kt("negate",te);continue}if(_.nonegate!==!0&&q.index===0){On();continue}}if(te==="+"){if(_.noextglob!==!0&&Ze()==="("&&Ze(2)!=="?"){kt("plus",te);continue}if(W&&W.value==="("||_.regex===!1){Ue({type:"plus",value:te,output:de});continue}if(W&&(W.type==="bracket"||W.type==="paren"||W.type==="brace")||q.parens>0){Ue({type:"plus",value:te});continue}Ue({type:"plus",value:de});continue}if(te==="@"){if(_.noextglob!==!0&&Ze()==="("&&Ze(2)!=="?"){Ue({type:"at",extglob:!0,value:te,output:""});continue}Ue({type:"text",value:te});continue}if(te!=="*"){(te==="$"||te==="^")&&(te=`\\${te}`);const ve=s.exec(Je());ve&&(te+=ve[0],q.index+=ve[0].length),Ue({type:"text",value:te});continue}if(W&&(W.type==="globstar"||W.star===!0)){W.type="star",W.star=!0,W.value+=te,W.output=ue,q.backtrack=!0,q.globstar=!0,en(te);continue}let ye=Je();if(_.noextglob!==!0&&/^\([^?]/.test(ye)){kt("star",te);continue}if(W.type==="star"){if(_.noglobstar===!0){en(te);continue}const ve=W.prev,je=ve.prev,He=ve.type==="slash"||ve.type==="bos",xt=je&&(je.type==="star"||je.type==="globstar");if(_.bash===!0&&(!He||ye[0]&&ye[0]!=="/")){Ue({type:"star",value:te,output:""});continue}const rt=q.braces>0&&(ve.type==="comma"||ve.type==="brace"),zt=we.length&&(ve.type==="pipe"||ve.type==="paren");if(!He&&ve.type!=="paren"&&!rt&&!zt){Ue({type:"star",value:te,output:""});continue}for(;ye.slice(0,3)==="/**";){const mt=T[q.index+4];if(mt&&mt!=="/")break;ye=ye.slice(3),en("/**",3)}if(ve.type==="bos"&&pt()){W.type="globstar",W.value+=te,W.output=ie(_),q.output=W.output,q.globstar=!0,en(te);continue}if(ve.type==="slash"&&ve.prev.type!=="bos"&&!xt&&pt()){q.output=q.output.slice(0,-(ve.output+W.output).length),ve.output=`(?:${ve.output}`,W.type="globstar",W.output=ie(_)+(_.strictSlashes?")":"|$)"),W.value+=te,q.globstar=!0,q.output+=ve.output+W.output,en(te);continue}if(ve.type==="slash"&&ve.prev.type!=="bos"&&ye[0]==="/"){const mt=ye[1]!==void 0?"|$":"";q.output=q.output.slice(0,-(ve.output+W.output).length),ve.output=`(?:${ve.output}`,W.type="globstar",W.output=`${ie(_)}${J}|${J}${mt})`,W.value+=te,q.output+=ve.output+W.output,q.globstar=!0,en(te+At()),Ue({type:"slash",value:"/",output:""});continue}if(ve.type==="bos"&&ye[0]==="/"){W.type="globstar",W.value+=te,W.output=`(?:^|${J}|${ie(_)}${J})`,q.output=W.output,q.globstar=!0,en(te+At()),Ue({type:"slash",value:"/",output:""});continue}q.output=q.output.slice(0,-W.output.length),W.type="globstar",W.output=ie(_),W.value+=te,q.output+=W.output,q.globstar=!0,en(te);continue}const at={type:"star",value:te,output:ue};if(_.bash===!0){at.output=".*?",(W.type==="bos"||W.type==="slash")&&(at.output=Ae+at.output),Ue(at);continue}if(W&&(W.type==="bracket"||W.type==="paren")&&_.regex===!0){at.output=te,Ue(at);continue}(q.index===q.start||W.type==="slash"||W.type==="dot")&&(W.type==="dot"?(q.output+=K,W.output+=K):_.dot===!0?(q.output+=G,W.output+=G):(q.output+=Ae,W.output+=Ae),Ze()!=="*"&&(q.output+=fe,W.output+=fe)),Ue(at)}for(;q.brackets>0;){if(_.strictBrackets===!0)throw new SyntaxError(v("closing","]"));q.output=a.escapeLast(q.output,"["),Nn("brackets")}for(;q.parens>0;){if(_.strictBrackets===!0)throw new SyntaxError(v("closing",")"));q.output=a.escapeLast(q.output,"("),Nn("parens")}for(;q.braces>0;){if(_.strictBrackets===!0)throw new SyntaxError(v("closing","}"));q.output=a.escapeLast(q.output,"{"),Nn("braces")}if(_.strictSlashes!==!0&&(W.type==="star"||W.type==="bracket")&&Ue({type:"maybe_slash",value:"",output:`${J}?`}),q.backtrack===!0){q.output="";for(const ye of q.tokens)q.output+=ye.output!=null?ye.output:ye.value,ye.suffix&&(q.output+=ye.suffix)}return q};return D.fastpaths=(T,R)=>{const _={...R},N=typeof _.maxLength=="number"?Math.min(o,_.maxLength):o,j=T.length;if(j>N)throw new SyntaxError(`Input length: ${j}, exceeds maximum allowed length: ${N}`);T=c[T]||T;const{DOT_LITERAL:F,SLASH_LITERAL:O,ONE_CHAR:I,DOTS_SLASH:re,NO_DOT:pe,NO_DOTS:ce,NO_DOTS_SLASH:de,STAR:J,START_ANCHOR:fe}=t.globChars(_.windows),U=_.dot?ce:pe,H=_.dot?de:pe,K=_.capture?"":"?:",G={negated:!1,prefix:""};let se=_.bash===!0?".*?":J;_.capture&&(se=`(${se})`);const L=Ae=>Ae.noglobstar===!0?se:`(${K}(?:(?!${fe}${Ae.dot?re:F}).)*?)`,$=Ae=>{switch(Ae){case"*":return`${U}${I}${se}`;case".*":return`${F}${I}${se}`;case"*.*":return`${U}${se}${F}${I}${se}`;case"*/*":return`${U}${se}${O}${I}${H}${se}`;case"**":return U+L(_);case"**/*":return`(?:${U}${L(_)}${O})?${H}${I}${se}`;case"**/*.*":return`(?:${U}${L(_)}${O})?${H}${se}${F}${I}${se}`;case"**/.*":return`(?:${U}${L(_)}${O})?${F}${I}${se}`;default:{const Se=/^(.*?)\.(\w+)$/.exec(Ae);if(!Se)return;const ue=$(Se[1]);return ue?ue+F+Se[2]:void 0}}},ne=a.removePrefix(T,G);let ie=$(ne);return ie&&_.strictSlashes!==!0&&(ie+=`${O}?`),ie},df=D,df}var hf,X1;function dL(){if(X1)return hf;X1=1;const t=cL(),a=fL(),o=fc(),i=cc(),s=c=>c&&typeof c=="object"&&!Array.isArray(c),u=(c,d,v=!1)=>{if(Array.isArray(c)){const w=c.map(T=>u(T,d,v));return T=>{for(const R of w){const _=R(T);if(_)return _}return!1}}const m=s(c)&&c.tokens&&c.input;if(c===""||typeof c!="string"&&!m)throw new TypeError("Expected pattern to be a non-empty string");const A=d||{},p=A.windows,C=m?u.compileRe(c,d):u.makeRe(c,d,!1,!0),b=C.state;delete C.state;let S=()=>!1;if(A.ignore){const w={...d,ignore:null,onMatch:null,onResult:null};S=u(A.ignore,w,v)}const x=(w,D=!1)=>{const{isMatch:T,match:R,output:_}=u.test(w,C,d,{glob:c,posix:p}),N={glob:c,state:b,regex:C,posix:p,input:w,output:_,match:R,isMatch:T};return typeof A.onResult=="function"&&A.onResult(N),T===!1?(N.isMatch=!1,D?N:!1):S(w)?(typeof A.onIgnore=="function"&&A.onIgnore(N),N.isMatch=!1,D?N:!1):(typeof A.onMatch=="function"&&A.onMatch(N),D?N:!0)};return v&&(x.state=b),x};return u.test=(c,d,v,{glob:m,posix:A}={})=>{if(typeof c!="string")throw new TypeError("Expected input to be a string");if(c==="")return{isMatch:!1,output:""};const p=v||{},C=p.format||(A?o.toPosixSlashes:null);let b=c===m,S=b&&C?C(c):c;return b===!1&&(S=C?C(c):c,b=S===m),(b===!1||p.capture===!0)&&(p.matchBase===!0||p.basename===!0?b=u.matchBase(c,d,v,A):b=d.exec(S)),{isMatch:!!b,match:b,output:S}},u.matchBase=(c,d,v)=>(d instanceof RegExp?d:u.makeRe(d,v)).test(o.basename(c)),u.isMatch=(c,d,v)=>u(d,v)(c),u.parse=(c,d)=>Array.isArray(c)?c.map(v=>u.parse(v,d)):a(c,{...d,fastpaths:!1}),u.scan=(c,d)=>t(c,d),u.compileRe=(c,d,v=!1,m=!1)=>{if(v===!0)return c.output;const A=d||{},p=A.contains?"":"^",C=A.contains?"":"$";let b=`${p}(?:${c.output})${C}`;c&&c.negated===!0&&(b=`^(?!${b}).*$`);const S=u.toRegex(b,d);return m===!0&&(S.state=c),S},u.makeRe=(c,d={},v=!1,m=!1)=>{if(!c||typeof c!="string")throw new TypeError("Expected a non-empty string");let A={negated:!1,fastpaths:!0};return d.fastpaths!==!1&&(c[0]==="."||c[0]==="*")&&(A.output=a.fastpaths(c,d)),A.output||(A=a(c,d)),u.compileRe(A,d,v,m)},u.toRegex=(c,d)=>{try{const v=d||{};return new RegExp(c,v.flags||(v.nocase?"i":""))}catch(v){if(d&&d.debug===!0)throw v;return/$^/}},u.constants=i,hf=u,hf}var pf,Z1;function hL(){if(Z1)return pf;Z1=1;const t=dL(),a=fc();function o(i,s,u=!1){return s&&(s.windows===null||s.windows===void 0)&&(s={...s,windows:a.isWindows()}),t(i,s,u)}return Object.assign(o,t),pf=o,pf}var pL=hL();const mL=El(pL);function vL(){const{pathname:t}=ft(),a=Ot(),{ogImageUrl:o}=a,i=y.useMemo(()=>{if(!o||typeof o=="string")return;const s=Object.keys(o).filter(u=>t.startsWith(u)||mL(u)(t));return s[s.length-1]},[o,t]);if(i&&o)return typeof o=="string"?o:o[i]}function Xf(t){const{children:a,content:o,filePath:i,frontmatter:s,lastUpdatedAt:u,path:c}=t,{pathname:d}=ft(),v=y.useRef(void 0);return y.useEffect(()=>{v.current=d}),g.jsxs(g.Fragment,{children:[g.jsx(gL,{frontmatter:s}),typeof window<"u"&&g.jsx(Py,{}),g.jsx(jD,{components:uL,children:g.jsx(U8,{frontmatter:s,path:c,children:g.jsx(Jy.Provider,{value:{content:o,filePath:i,frontmatter:s,lastUpdatedAt:u,previousPath:v.current},children:a})})})]})}function gL({frontmatter:t}){const a=Ot(),o=vL(),{baseUrl:i,font:s,iconUrl:u,logoUrl:c}=a,d=t?.description??a.description,v=t?.title??a.title,m=(()=>{if(a.title&&!v.includes(a.title))return a.titleTemplate})(),A=typeof window<"u"&&window.location.hostname==="localhost",p=m?m.replace("%s",v):v;return g.jsxs(g.Fragment,{children:[p&&g.jsx("title",{children:p}),i&&!0&&!A&&g.jsx("base",{href:i}),d!=="undefined"&&g.jsx("meta",{name:"description",content:d}),u&&typeof u=="string"&&g.jsx("link",{rel:"icon",href:u,type:mf(u)}),u&&typeof u!="string"&&g.jsx("link",{rel:"icon",href:u.light,type:mf(u.light)}),u&&typeof u!="string"&&g.jsx("link",{rel:"icon",href:u.dark,type:mf(u.dark),media:"(prefers-color-scheme: dark)"}),g.jsx("meta",{property:"og:type",content:"website"}),g.jsx("meta",{property:"og:title",content:v||a.title}),i&&g.jsx("meta",{property:"og:url",content:i}),d!=="undefined"&&g.jsx("meta",{property:"og:description",content:d}),o&&g.jsx("meta",{property:"og:image",content:o.replace("%logo",`${i||""}${typeof c=="string"?c:c?.dark||""}`).replace("%title",v||"").replace("%description",(d!=="undefined"?d:"")||"")}),(s?.default?.google||s?.mono?.google)&&g.jsx("link",{rel:"preconnect",href:"https://fonts.googleapis.com"}),(s?.default?.google||s?.mono?.google)&&g.jsx("link",{rel:"preconnect",href:"https://fonts.gstatic.com",crossOrigin:""}),s?.default?.google&&g.jsx("link",{href:`https://fonts.googleapis.com/css2?family=${s.default.google}:wght@300;400;500&display=swap`,rel:"stylesheet"}),s?.mono?.google&&g.jsx("link",{href:`https://fonts.googleapis.com/css2?family=${s.mono.google}:wght@300;400;500&display=swap`,rel:"stylesheet"}),g.jsx("meta",{name:"twitter:card",content:"summary_large_image"}),o&&g.jsx("meta",{property:"twitter:image",content:o.replace("%logo",`${i||""}${typeof c=="string"?c:c?.dark||""}`).replace("%title",v?encodeURIComponent(v):"").replace("%description",d?encodeURIComponent(d):"")})]})}function mf(t){if(t.endsWith(".svg"))return"image/svg+xml";if(t.endsWith(".png"))return"image/png";if(t.endsWith(".jpg"))return"image/jpeg";if(t.endsWith(".ico"))return"image/x-icon";if(t.endsWith(".webp"))return"image/webp"}function yL(t){if(!t||!t.message)return!1;const a=t.message.toLowerCase();return a.includes("failed to fetch dynamically imported module")||a.includes("error loading dynamically imported module")||a.includes("dynamically imported module")}function lh(t){if(yL(t)){if(sessionStorage.getItem(wu)){sessionStorage.removeItem(wu);return}sessionStorage.setItem(wu,"true"),window.location.reload()}}function AL(){sessionStorage.removeItem(wu)}const wu="vocs.reload",CL=(()=>{const t=md.find(({path:a})=>a==="*");return t?{path:t.path,lazy:async()=>{try{const{frontmatter:a,...o}=await t.lazy();return{...o,element:g.jsx(Xf,{frontmatter:a,path:t.path,children:g.jsx(Yf,{children:g.jsx(o.default,{})})})}}catch(a){throw lh(a),a}}}:{path:"*",lazy:void 0,element:g.jsx(Xf,{frontmatter:{layout:"minimal"},path:"*",children:g.jsx(Yf,{children:g.jsx(d8,{})})})}})(),J1=[...md.filter(({path:t})=>t!=="*").map(t=>({path:t.path,lazy:async()=>{try{const{frontmatter:a,...o}=await t.lazy();return{...o,element:g.jsx(Xf,{content:decodeURIComponent(t.content??""),filePath:t.filePath,frontmatter:a,lastUpdatedAt:t.lastUpdatedAt,path:t.path,children:g.jsx(Yf,{children:g.jsx(o.default,{})})})}}catch(a){throw lh(a),a}}})),CL];async function bL(t,a){const o=Ha(t,window.location,a)?.filter(i=>i.route.lazy);if(o&&o?.length>0)try{await Promise.all(o.map(async i=>{const s=typeof i.route.lazy=="function"?await i.route.lazy():i.route.lazy;Object.assign(i.route,{...s,lazy:void 0})}))}catch(i){throw lh(i),i}}function EL(){const t=document.querySelectorAll('style[data-vocs-temp-style="true"]');for(const a of t)a.remove()}SL();async function SL(){const t=$y().basePath;await bL(J1,t),EL(),AL();const a=j7(J1,{basename:t});Sb.hydrateRoot(document.getElementById("app"),g.jsx(X7,{children:g.jsx(gb,{children:g.jsx(o7,{router:a})})}))}export{me as c,g as j,LD as u}; |
| 1 | + | import{c as l,j as e,u as m}from"./index-DO6OtFZH.js";function r({children:t,className:n,href:s,variant:c,type:o="button"}){const a=l(n,"inline-flex items-center justify-center px-4 py-2 text-sm font-medium rounded-md border border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-offset-2 hover:opacity-90",c==="accent"?"hover:opacity-90 focus:ring-orange-400 text-zinc-900 bg-[#ffb757]":"bg-zinc-900! text-zinc-200! hover:bg-zinc-800! focus:ring-gray-500!");return o==="link"?e.jsx("a",{href:s,className:a,children:t}):e.jsx("button",{type:o,className:a,...o!=="submit"&&s?{href:s}:{},children:t})}function u(){return e.jsxs("main",{className:"flex w-full sm:h-[85vh] min-h-[85vh] mt-6 mx-auto flex-col items-center justify-center gap-12 p-4 relative",style:{backgroundImage:"url('/bg.png')",backgroundPosition:"center",backgroundRepeat:"no-repeat",backgroundSize:"cover",zIndex:0},children:[e.jsx("div",{className:"absolute inset-0 pointer-events-none",style:{backgroundColor:"rgba(18, 17, 19, 0.7)",zIndex:-1}}),e.jsxs("div",{className:"flex flex-col items-center gap-12",children:[e.jsx("h1",{className:"text-center sm:text-6xl text-4xl font-black",style:{fontFamily:"'CommitMono', monospace"},children:"Andromeda"}),e.jsx("h3",{className:"text-center sm:text-2xl text-lg font-semibold",style:{fontFamily:"'CommitMono', monospace"},children:"Minimal, self-hosted personal software in Rust"})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx(r,{type:"link",variant:"accent",href:"/quickstart",children:"Get Started"}),e.jsx(r,{type:"link",href:"https://github.com/stevedylandev/andromeda",children:"GitHub"})]})]})}const x={layout:"landing",content:{horizontalPadding:"0px",width:"100%",verticalPadding:"0px"}};function i(t){return e.jsx(u,{})}function f(t={}){const{wrapper:n}={...m(),...t.components};return n?e.jsx(n,{...t,children:e.jsx(i,{...t})}):i()}export{f as default,x as frontmatter}; |
| 1 | + | import{u as r,j as s}from"./index-DO6OtFZH.js";const l={title:"Jotts",description:"undefined"};function n(i){const e={a:"a",code:"code",div:"div",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",li:"li",p:"p",pre:"pre",span:"span",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...r(),...i.components};return s.jsxs(s.Fragment,{children:[s.jsx(e.header,{children:s.jsxs(e.h1,{id:"jotts",children:["Jotts",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#jotts",children:s.jsx(e.div,{"data-autolink-icon":!0})})]})}),` |
|
| 2 | + | `,s.jsx(e.p,{children:"A minimal notes app"}),` |
|
| 3 | + | `,s.jsxs(e.h2,{id:"overview",children:["Overview",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#overview",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 4 | + | `,s.jsx(e.p,{children:"A simple, self-hosted markdown note app built with Rust."}),` |
|
| 5 | + | `,s.jsxs(e.ul,{children:[` |
|
| 6 | + | `,s.jsx(e.li,{children:"Single ~7MB Rust binary with embedded assets"}),` |
|
| 7 | + | `,s.jsx(e.li,{children:"Password authentication with session cookies"}),` |
|
| 8 | + | `,s.jsx(e.li,{children:"Create, edit, and delete markdown notes"}),` |
|
| 9 | + | `,s.jsx(e.li,{children:"Markdown rendering with strikethrough, tables, and task lists"}),` |
|
| 10 | + | `,s.jsx(e.li,{children:"Dark themed UI with Commit Mono font"}),` |
|
| 11 | + | `,s.jsx(e.li,{children:"SQLite for persistent storage"}),` |
|
| 12 | + | `]}),` |
|
| 13 | + | `,s.jsxs(e.h2,{id:"quickstart",children:["Quickstart",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#quickstart",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 14 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"git"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" clone"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" https://github.com/stevedylandev/andromeda.git"})]}),` |
|
| 15 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:"cd"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" andromeda"})]}),` |
|
| 16 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cp"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" apps/jotts/.env.example"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" .env"})]}),` |
|
| 17 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#BDC4CC","--shiki-dark":"#BDC4CC"},children:"# Edit .env with your password"})}),` |
|
| 18 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" run"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" jotts"})]})]})})}),` |
|
| 19 | + | `,s.jsxs(e.h3,{id:"environment-variables",children:["Environment Variables",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#environment-variables",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 20 | + | `,s.jsxs(e.table,{children:[s.jsx(e.thead,{children:s.jsxs(e.tr,{children:[s.jsx(e.th,{children:"Variable"}),s.jsx(e.th,{children:"Description"}),s.jsx(e.th,{children:"Default"})]})}),s.jsxs(e.tbody,{children:[s.jsxs(e.tr,{children:[s.jsx(e.td,{children:s.jsx(e.code,{children:"JOTTS_PASSWORD"})}),s.jsx(e.td,{children:"Password for login authentication"}),s.jsx(e.td,{children:s.jsx(e.code,{children:"changeme"})})]}),s.jsxs(e.tr,{children:[s.jsx(e.td,{children:s.jsx(e.code,{children:"JOTTS_DB_PATH"})}),s.jsx(e.td,{children:"SQLite database file path"}),s.jsx(e.td,{children:s.jsx(e.code,{children:"jotts.sqlite"})})]}),s.jsxs(e.tr,{children:[s.jsx(e.td,{children:s.jsx(e.code,{children:"HOST"})}),s.jsx(e.td,{children:"Server bind address"}),s.jsx(e.td,{children:s.jsx(e.code,{children:"127.0.0.1"})})]}),s.jsxs(e.tr,{children:[s.jsx(e.td,{children:s.jsx(e.code,{children:"PORT"})}),s.jsx(e.td,{children:"Server port"}),s.jsx(e.td,{children:s.jsx(e.code,{children:"3000"})})]}),s.jsxs(e.tr,{children:[s.jsx(e.td,{children:s.jsx(e.code,{children:"COOKIE_SECURE"})}),s.jsx(e.td,{children:"Enable HTTPS-only cookies"}),s.jsx(e.td,{children:s.jsx(e.code,{children:"false"})})]})]})]}),` |
|
| 21 | + | `,s.jsxs(e.h2,{id:"structure",children:["Structure",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#structure",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 22 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"jotts/"})}),` |
|
| 23 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── src/"})}),` |
|
| 24 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── main.rs # App entrypoint, env vars, starts server"})}),` |
|
| 25 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── server.rs # Axum router, HTTP handlers, and templates"})}),` |
|
| 26 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── auth.rs # Password verification and session management"})}),` |
|
| 27 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ └── db.rs # SQLite database layer (notes, sessions)"})}),` |
|
| 28 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── templates/ # Askama HTML templates"})}),` |
|
| 29 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── base.html # Base layout with header and nav"})}),` |
|
| 30 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── login.html # Login page"})}),` |
|
| 31 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── index.html # Note list"})}),` |
|
| 32 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── view.html # Single note display"})}),` |
|
| 33 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── new.html # Create note form"})}),` |
|
| 34 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ └── edit.html # Edit note form"})}),` |
|
| 35 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── static/ # Favicons, og:image, styles, and webmanifest"})}),` |
|
| 36 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── assets/ # Commit Mono font files"})}),` |
|
| 37 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── Dockerfile"})}),` |
|
| 38 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"└── docker-compose.yml"})})]})})}),` |
|
| 39 | + | `,s.jsxs(e.h2,{id:"deployment",children:["Deployment",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#deployment",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 40 | + | `,s.jsxs(e.h3,{id:"railway",children:["Railway",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#railway",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 41 | + | `,s.jsx(e.p,{children:s.jsx(e.a,{href:"https://railway.com/deploy/DLhUhH?referralCode=JGcIp6",children:s.jsx(e.img,{src:"https://railway.com/button.svg",alt:"Deploy on Railway"})})}),` |
|
| 42 | + | `,s.jsxs(e.h3,{id:"docker",children:["Docker",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#docker",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 43 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:"cd"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" apps/jotts"})]}),` |
|
| 44 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cp"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" .env.example"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" .env"})]}),` |
|
| 45 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#BDC4CC","--shiki-dark":"#BDC4CC"},children:"# Edit .env with your password"})}),` |
|
| 46 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"docker"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" compose"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" up"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -d"})]})]})})}),` |
|
| 47 | + | `,s.jsxs(e.p,{children:["This will start Jotts on port ",s.jsx(e.code,{children:"3000"})," with a persistent volume for the SQLite database."]}),` |
|
| 48 | + | `,s.jsxs(e.h3,{id:"binary",children:["Binary",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#binary",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 49 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsx(e.code,{children:s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" build"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" --release"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" jotts"})]})})})}),` |
|
| 50 | + | `,s.jsxs(e.p,{children:["The resulting binary is self-contained with all assets embedded. Copy it to your server with a configured ",s.jsx(e.code,{children:".env"})," file and run it directly."]})]})}function d(i={}){const{wrapper:e}={...r(),...i.components};return e?s.jsx(e,{...i,children:s.jsx(n,{...i})}):n(i)}export{d as default,l as frontmatter}; |
| 1 | + | import{u as r,j as s}from"./index-DO6OtFZH.js";const l={title:"OG",description:"undefined"};function n(i){const e={a:"a",code:"code",div:"div",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",li:"li",p:"p",pre:"pre",span:"span",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...r(),...i.components};return s.jsxs(s.Fragment,{children:[s.jsx(e.header,{children:s.jsxs(e.h1,{id:"og",children:["OG",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#og",children:s.jsx(e.div,{"data-autolink-icon":!0})})]})}),` |
|
| 2 | + | `,s.jsx(e.p,{children:"A simple web tool for inspecting Open Graph tags on any URL."}),` |
|
| 3 | + | `,s.jsxs(e.h2,{id:"overview",children:["Overview",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#overview",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 4 | + | `,s.jsx(e.p,{children:"A self-hosted Open Graph tag inspector built with Rust. Enter any URL and instantly see its OG metadata."}),` |
|
| 5 | + | `,s.jsxs(e.ul,{children:[` |
|
| 6 | + | `,s.jsx(e.li,{children:"Single Rust binary with embedded assets"}),` |
|
| 7 | + | `,s.jsx(e.li,{children:"Inspects title, description, image, and other OG tags"}),` |
|
| 8 | + | `,s.jsx(e.li,{children:"Dark themed UI with Commit Mono font"}),` |
|
| 9 | + | `,s.jsx(e.li,{children:"No database needed -- fully stateless"}),` |
|
| 10 | + | `]}),` |
|
| 11 | + | `,s.jsxs(e.h2,{id:"quickstart",children:["Quickstart",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#quickstart",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 12 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"git"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" clone"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" https://github.com/stevedylandev/andromeda.git"})]}),` |
|
| 13 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:"cd"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" andromeda"})]}),` |
|
| 14 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" run"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" og"})]})]})})}),` |
|
| 15 | + | `,s.jsxs(e.h3,{id:"environment-variables",children:["Environment Variables",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#environment-variables",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 16 | + | `,s.jsxs(e.table,{children:[s.jsx(e.thead,{children:s.jsxs(e.tr,{children:[s.jsx(e.th,{children:"Variable"}),s.jsx(e.th,{children:"Description"}),s.jsx(e.th,{children:"Default"})]})}),s.jsx(e.tbody,{children:s.jsxs(e.tr,{children:[s.jsx(e.td,{children:s.jsx(e.code,{children:"PORT"})}),s.jsx(e.td,{children:"Server port"}),s.jsx(e.td,{children:s.jsx(e.code,{children:"3000"})})]})})]}),` |
|
| 17 | + | `,s.jsxs(e.h2,{id:"structure",children:["Structure",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#structure",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 18 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"og/"})}),` |
|
| 19 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── src/"})}),` |
|
| 20 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── main.rs # Entry point and server startup"})}),` |
|
| 21 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── server.rs # Axum routes and request handling"})}),` |
|
| 22 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ └── og.rs # Open Graph tag fetching and parsing"})}),` |
|
| 23 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── templates/ # Askama HTML templates"})}),` |
|
| 24 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── base.html # Base layout"})}),` |
|
| 25 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── index.html # Search form"})}),` |
|
| 26 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ └── results.html # OG tag results display"})}),` |
|
| 27 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── static/ # Fonts, favicons, and styles"})}),` |
|
| 28 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── Dockerfile"})}),` |
|
| 29 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"└── docker-compose.yml"})})]})})}),` |
|
| 30 | + | `,s.jsxs(e.h2,{id:"deployment",children:["Deployment",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#deployment",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 31 | + | `,s.jsxs(e.h3,{id:"railway",children:["Railway",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#railway",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 32 | + | `,s.jsx(e.p,{children:s.jsx(e.a,{href:"https://railway.com/deploy/OdXBt_?referralCode=JGcIp6",children:s.jsx(e.img,{src:"https://railway.com/button.svg",alt:"Deploy on Railway"})})}),` |
|
| 33 | + | `,s.jsxs(e.h3,{id:"docker",children:["Docker",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#docker",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 34 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:"cd"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" apps/og"})]}),` |
|
| 35 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"docker"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" compose"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" up"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -d"})]})]})})}),` |
|
| 36 | + | `,s.jsxs(e.h3,{id:"binary",children:["Binary",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#binary",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 37 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsx(e.code,{children:s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" build"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" --release"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" og"})]})})})}),` |
|
| 38 | + | `,s.jsx(e.p,{children:"The resulting binary is self-contained with all assets embedded. Copy it to your server and run it directly."})]})}function d(i={}){const{wrapper:e}={...r(),...i.components};return e?s.jsx(e,{...i,children:s.jsx(n,{...i})}):n(i)}export{d as default,l as frontmatter}; |
| 1 | + | import{u as r,j as s}from"./index-DO6OtFZH.js";const l={title:"Parcels",description:"undefined"};function n(i){const e={a:"a",aside:"aside",code:"code",div:"div",em:"em",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",li:"li",p:"p",pre:"pre",span:"span",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...r(),...i.components};return s.jsxs(s.Fragment,{children:[s.jsx(e.header,{children:s.jsxs(e.h1,{id:"parcels",children:["Parcels",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#parcels",children:s.jsx(e.div,{"data-autolink-icon":!0})})]})}),` |
|
| 2 | + | `,s.jsx(e.p,{children:"A minimal package tracking app"}),` |
|
| 3 | + | `,s.jsx(e.aside,{"data-callout":"warning",children:s.jsx(e.p,{children:"This app originally used USPS, but starting April 1st 2026, it has become much harder to obtain/maintain API keys."})}),` |
|
| 4 | + | `,s.jsxs(e.h2,{id:"overview",children:["Overview",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#overview",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 5 | + | `,s.jsx(e.p,{children:"A self-hosted package tracker for USPS. Track your packages without logging into USPS every time."}),` |
|
| 6 | + | `,s.jsxs(e.ul,{children:[` |
|
| 7 | + | `,s.jsx(e.li,{children:"Single ~7MB Rust binary"}),` |
|
| 8 | + | `,s.jsx(e.li,{children:"Averages around ~10MB of RAM usage"}),` |
|
| 9 | + | `,s.jsx(e.li,{children:"Password authentication"}),` |
|
| 10 | + | `,s.jsx(e.li,{children:"Track USPS packages with custom labels"}),` |
|
| 11 | + | `,s.jsx(e.li,{children:"Delete packages you no longer want to track"}),` |
|
| 12 | + | `]}),` |
|
| 13 | + | `,s.jsxs(e.h2,{id:"quickstart",children:["Quickstart",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#quickstart",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 14 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"git"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" clone"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" https://github.com/stevedylandev/andromeda.git"})]}),` |
|
| 15 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:"cd"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" andromeda"})]}),` |
|
| 16 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cp"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" apps/parcels/.env.example"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" .env"})]}),` |
|
| 17 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#BDC4CC","--shiki-dark":"#BDC4CC"},children:"# Edit .env with your USPS API credentials and app password"})}),` |
|
| 18 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" run"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" parcels"})]})]})})}),` |
|
| 19 | + | `,s.jsxs(e.p,{children:["You'll need a ",s.jsx(e.a,{href:"https://developer.usps.com",children:"USPS Web Tools API"})," account to get your ",s.jsx(e.code,{children:"USPS_CLIENT_ID"})," and ",s.jsx(e.code,{children:"USPS_CLIENT_SECRET"}),"."]}),` |
|
| 20 | + | `,s.jsxs(e.h3,{id:"environment-variables",children:["Environment Variables",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#environment-variables",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 21 | + | `,s.jsxs(e.table,{children:[s.jsx(e.thead,{children:s.jsxs(e.tr,{children:[s.jsx(e.th,{children:"Variable"}),s.jsx(e.th,{children:"Description"}),s.jsx(e.th,{children:"Default"})]})}),s.jsxs(e.tbody,{children:[s.jsxs(e.tr,{children:[s.jsx(e.td,{children:s.jsx(e.code,{children:"APP_PASSWORD"})}),s.jsx(e.td,{children:"Password for login authentication"}),s.jsx(e.td,{children:s.jsx(e.em,{children:"required"})})]}),s.jsxs(e.tr,{children:[s.jsx(e.td,{children:s.jsx(e.code,{children:"PARCELS_DB_PATH"})}),s.jsx(e.td,{children:"SQLite database file path"}),s.jsx(e.td,{children:s.jsx(e.code,{children:"parcels.db"})})]}),s.jsxs(e.tr,{children:[s.jsx(e.td,{children:s.jsx(e.code,{children:"USPS_CLIENT_ID"})}),s.jsx(e.td,{children:"USPS OAuth2 client ID"}),s.jsx(e.td,{children:s.jsx(e.em,{children:"required"})})]}),s.jsxs(e.tr,{children:[s.jsx(e.td,{children:s.jsx(e.code,{children:"USPS_CLIENT_SECRET"})}),s.jsx(e.td,{children:"USPS OAuth2 client secret"}),s.jsx(e.td,{children:s.jsx(e.em,{children:"required"})})]}),s.jsxs(e.tr,{children:[s.jsx(e.td,{children:s.jsx(e.code,{children:"PORT"})}),s.jsx(e.td,{children:"Server port"}),s.jsx(e.td,{children:s.jsx(e.code,{children:"3000"})})]}),s.jsxs(e.tr,{children:[s.jsx(e.td,{children:s.jsx(e.code,{children:"COOKIE_SECURE"})}),s.jsx(e.td,{children:"Enable HTTPS-only cookies"}),s.jsx(e.td,{children:s.jsx(e.code,{children:"false"})})]})]})]}),` |
|
| 22 | + | `,s.jsxs(e.h2,{id:"structure",children:["Structure",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#structure",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 23 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"parcels/"})}),` |
|
| 24 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── src/"})}),` |
|
| 25 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── main.rs # Axum web server, routes, and app state"})}),` |
|
| 26 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── auth.rs # Password verification and session management"})}),` |
|
| 27 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── db.rs # SQLite database layer (packages, events, sessions)"})}),` |
|
| 28 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ └── usps.rs # USPS API integration with OAuth2 token caching"})}),` |
|
| 29 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── templates/ # Askama HTML templates"})}),` |
|
| 30 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── base.html # Base layout"})}),` |
|
| 31 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── index.html # Package list"})}),` |
|
| 32 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── detail.html # Package detail with tracking events"})}),` |
|
| 33 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── add.html # Add package form"})}),` |
|
| 34 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ └── login.html # Login page"})}),` |
|
| 35 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── static/ # Fonts, favicons, and images"})}),` |
|
| 36 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── Dockerfile"})}),` |
|
| 37 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"└── docker-compose.yml"})})]})})}),` |
|
| 38 | + | `,s.jsxs(e.h2,{id:"deployment",children:["Deployment",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#deployment",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 39 | + | `,s.jsxs(e.h3,{id:"railway",children:["Railway",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#railway",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 40 | + | `,s.jsx(e.p,{children:s.jsx(e.a,{href:"https://railway.com/deploy/HNQUs4?referralCode=JGcIp6",children:s.jsx(e.img,{src:"https://railway.com/button.svg",alt:"Deploy on Railway"})})}),` |
|
| 41 | + | `,s.jsxs(e.h3,{id:"docker",children:["Docker",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#docker",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 42 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:"cd"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" apps/parcels"})]}),` |
|
| 43 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cp"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" .env.example"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" .env"})]}),` |
|
| 44 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#BDC4CC","--shiki-dark":"#BDC4CC"},children:"# Edit .env with your credentials"})}),` |
|
| 45 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"docker"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" compose"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" up"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -d"})]})]})})}),` |
|
| 46 | + | `,s.jsxs(e.p,{children:["This will start Parcels on port ",s.jsx(e.code,{children:"3000"})," with a persistent volume for the SQLite database."]}),` |
|
| 47 | + | `,s.jsxs(e.h3,{id:"binary",children:["Binary",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#binary",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 48 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsx(e.code,{children:s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" build"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" --release"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" parcels"})]})})})}),` |
|
| 49 | + | `,s.jsxs(e.p,{children:["The resulting binary is self-contained (~7MB). Copy it to your server with a configured ",s.jsx(e.code,{children:".env"})," file and run it directly."]})]})}function d(i={}){const{wrapper:e}={...r(),...i.components};return e?s.jsx(e,{...i,children:s.jsx(n,{...i})}):n(i)}export{d as default,l as frontmatter}; |
| 1 | + | import{u as n,j as s}from"./index-DO6OtFZH.js";const l={title:"Quickstart",description:"undefined"};function r(e){const i={a:"a",code:"code",div:"div",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",span:"span",strong:"strong",ul:"ul",...n(),...e.components};return s.jsxs(s.Fragment,{children:[s.jsx(i.header,{children:s.jsxs(i.h1,{id:"quickstart",children:["Quickstart",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#quickstart",children:s.jsx(i.div,{"data-autolink-icon":!0})})]})}),` |
|
| 2 | + | `,s.jsx(i.p,{children:"Get up and running with any Andromeda app in minutes."}),` |
|
| 3 | + | `,s.jsxs(i.h2,{id:"prerequisites",children:["Prerequisites",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#prerequisites",children:s.jsx(i.div,{"data-autolink-icon":!0})})]}),` |
|
| 4 | + | `,s.jsxs(i.p,{children:["Make sure ",s.jsx(i.a,{href:"https://www.rust-lang.org/tools/install",children:"Rust"})," is installed:"]}),` |
|
| 5 | + | `,s.jsx(s.Fragment,{children:s.jsx(i.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsx(i.code,{children:s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"rustc"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" --version"})]})})})}),` |
|
| 6 | + | `,s.jsxs(i.h2,{id:"clone-the-workspace",children:["Clone the Workspace",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#clone-the-workspace",children:s.jsx(i.div,{"data-autolink-icon":!0})})]}),` |
|
| 7 | + | `,s.jsx(s.Fragment,{children:s.jsx(i.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(i.code,{children:[s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"git"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" clone"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" https://github.com/stevedylandev/andromeda.git"})]}),` |
|
| 8 | + | `,s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:"cd"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" andromeda"})]})]})})}),` |
|
| 9 | + | `,s.jsxs(i.h2,{id:"build-all-apps",children:["Build All Apps",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#build-all-apps",children:s.jsx(i.div,{"data-autolink-icon":!0})})]}),` |
|
| 10 | + | `,s.jsx(s.Fragment,{children:s.jsx(i.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsx(i.code,{children:s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" build"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" --release"})]})})})}),` |
|
| 11 | + | `,s.jsxs(i.h2,{id:"run-a-specific-app",children:["Run a Specific App",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#run-a-specific-app",children:s.jsx(i.div,{"data-autolink-icon":!0})})]}),` |
|
| 12 | + | `,s.jsxs(i.p,{children:["Each app is a workspace member. Run any of them with ",s.jsx(i.code,{children:"cargo run -p"}),":"]}),` |
|
| 13 | + | `,s.jsx(s.Fragment,{children:s.jsx(i.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(i.code,{children:[s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" run"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" sipp"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" --"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" server"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" --port"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" 3000"})]}),` |
|
| 14 | + | `,s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" run"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" feeds"})]}),` |
|
| 15 | + | `,s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" run"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" parcels"})]}),` |
|
| 16 | + | `,s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" run"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" jotts"})]}),` |
|
| 17 | + | `,s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" run"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" og"})]}),` |
|
| 18 | + | `,s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" run"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" shrink"})]})]})})}),` |
|
| 19 | + | `,s.jsxs(i.p,{children:["Most apps start on ",s.jsx(i.code,{children:"http://localhost:3000"})," by default. Check each app's page for specific environment variables and configuration."]}),` |
|
| 20 | + | `,s.jsxs(i.h2,{id:"environment-variables",children:["Environment Variables",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#environment-variables",children:s.jsx(i.div,{"data-autolink-icon":!0})})]}),` |
|
| 21 | + | `,s.jsxs(i.p,{children:["Most apps use a ",s.jsx(i.code,{children:".env"})," file for configuration. Copy the example file and fill in your values:"]}),` |
|
| 22 | + | `,s.jsx(s.Fragment,{children:s.jsx(i.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsx(i.code,{children:s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cp"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" apps/"}),s.jsx(i.span,{style:{color:"#FF9492","--shiki-dark":"#FF9492"},children:"<"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:"app-nam"}),s.jsx(i.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"e"}),s.jsx(i.span,{style:{color:"#FF9492","--shiki-dark":"#FF9492"},children:">"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:"/.env.example"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" .env"})]})})})}),` |
|
| 23 | + | `,s.jsxs(i.h2,{id:"deployment",children:["Deployment",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#deployment",children:s.jsx(i.div,{"data-autolink-icon":!0})})]}),` |
|
| 24 | + | `,s.jsx(i.p,{children:"Every app compiles to a single binary with embedded assets, making deployment straightforward. Each app supports:"}),` |
|
| 25 | + | `,s.jsxs(i.ul,{children:[` |
|
| 26 | + | `,s.jsxs(i.li,{children:[s.jsx(i.strong,{children:"Railway"})," - one-click deploy buttons on each app's page"]}),` |
|
| 27 | + | `,s.jsxs(i.li,{children:[s.jsx(i.strong,{children:"Docker"})," - ",s.jsx(i.code,{children:"docker compose up -d"})]}),` |
|
| 28 | + | `,s.jsxs(i.li,{children:[s.jsx(i.strong,{children:"Binary"})," - copy the binary to your server and run it directly"]}),` |
|
| 29 | + | `]})]})}function d(e={}){const{wrapper:i}={...n(),...e.components};return i?s.jsx(i,{...e,children:s.jsx(r,{...e})}):r(e)}export{d as default,l as frontmatter}; |
| 1 | + | import{u as n,j as s}from"./index-DO6OtFZH.js";const d={title:"Shrink",description:"undefined"};function r(e){const i={a:"a",code:"code",div:"div",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",li:"li",p:"p",pre:"pre",span:"span",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...n(),...e.components};return s.jsxs(s.Fragment,{children:[s.jsx(i.header,{children:s.jsxs(i.h1,{id:"shrink",children:["Shrink",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#shrink",children:s.jsx(i.div,{"data-autolink-icon":!0})})]})}),` |
|
| 2 | + | `,s.jsx(i.p,{children:"A minimal image compression app"}),` |
|
| 3 | + | `,s.jsxs(i.h2,{id:"overview",children:["Overview",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#overview",children:s.jsx(i.div,{"data-autolink-icon":!0})})]}),` |
|
| 4 | + | `,s.jsx(i.p,{children:"A simple self-hosted tool for compressing and resizing images. Upload an image, set your desired quality and optional width, and download the compressed JPEG."}),` |
|
| 5 | + | `,s.jsxs(i.ul,{children:[` |
|
| 6 | + | `,s.jsx(i.li,{children:"Single Rust binary"}),` |
|
| 7 | + | `,s.jsx(i.li,{children:"Compress images to JPEG with configurable quality (1-100)"}),` |
|
| 8 | + | `,s.jsx(i.li,{children:"Optional resize by width (preserves aspect ratio)"}),` |
|
| 9 | + | `,s.jsx(i.li,{children:"20MB upload limit"}),` |
|
| 10 | + | `]}),` |
|
| 11 | + | `,s.jsxs(i.h2,{id:"quickstart",children:["Quickstart",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#quickstart",children:s.jsx(i.div,{"data-autolink-icon":!0})})]}),` |
|
| 12 | + | `,s.jsx(s.Fragment,{children:s.jsx(i.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(i.code,{children:[s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"git"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" clone"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" https://github.com/stevedylandev/andromeda.git"})]}),` |
|
| 13 | + | `,s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:"cd"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" andromeda"})]}),` |
|
| 14 | + | `,s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" run"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" shrink"})]})]})})}),` |
|
| 15 | + | `,s.jsxs(i.h3,{id:"environment-variables",children:["Environment Variables",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#environment-variables",children:s.jsx(i.div,{"data-autolink-icon":!0})})]}),` |
|
| 16 | + | `,s.jsxs(i.table,{children:[s.jsx(i.thead,{children:s.jsxs(i.tr,{children:[s.jsx(i.th,{children:"Variable"}),s.jsx(i.th,{children:"Description"}),s.jsx(i.th,{children:"Default"})]})}),s.jsxs(i.tbody,{children:[s.jsxs(i.tr,{children:[s.jsx(i.td,{children:s.jsx(i.code,{children:"HOST"})}),s.jsx(i.td,{children:"Server bind host"}),s.jsx(i.td,{children:s.jsx(i.code,{children:"127.0.0.1"})})]}),s.jsxs(i.tr,{children:[s.jsx(i.td,{children:s.jsx(i.code,{children:"PORT"})}),s.jsx(i.td,{children:"Server bind port"}),s.jsx(i.td,{children:s.jsx(i.code,{children:"3000"})})]})]})]}),` |
|
| 17 | + | `,s.jsxs(i.h2,{id:"structure",children:["Structure",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#structure",children:s.jsx(i.div,{"data-autolink-icon":!0})})]}),` |
|
| 18 | + | `,s.jsx(s.Fragment,{children:s.jsx(i.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(i.code,{children:[s.jsx(i.span,{className:"line",children:s.jsx(i.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"shrink/"})}),` |
|
| 19 | + | `,s.jsx(i.span,{className:"line",children:s.jsx(i.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── src/"})}),` |
|
| 20 | + | `,s.jsx(i.span,{className:"line",children:s.jsx(i.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── main.rs # Entry point and server startup"})}),` |
|
| 21 | + | `,s.jsx(i.span,{className:"line",children:s.jsx(i.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ └── server.rs # Axum routes and image compression logic"})}),` |
|
| 22 | + | `,s.jsx(i.span,{className:"line",children:s.jsx(i.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── templates/"})}),` |
|
| 23 | + | `,s.jsx(i.span,{className:"line",children:s.jsx(i.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ └── index.html # Upload UI"})}),` |
|
| 24 | + | `,s.jsx(i.span,{className:"line",children:s.jsx(i.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── static/ # Fonts and static assets"})}),` |
|
| 25 | + | `,s.jsx(i.span,{className:"line",children:s.jsx(i.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── Dockerfile"})}),` |
|
| 26 | + | `,s.jsx(i.span,{className:"line",children:s.jsx(i.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"└── docker-compose.yml"})})]})})}),` |
|
| 27 | + | `,s.jsxs(i.h2,{id:"deployment",children:["Deployment",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#deployment",children:s.jsx(i.div,{"data-autolink-icon":!0})})]}),` |
|
| 28 | + | `,s.jsxs(i.h3,{id:"railway",children:["Railway",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#railway",children:s.jsx(i.div,{"data-autolink-icon":!0})})]}),` |
|
| 29 | + | `,s.jsx(i.p,{children:s.jsx(i.a,{href:"https://railway.com/deploy/enYUFb?referralCode=JGcIp6",children:s.jsx(i.img,{src:"https://railway.com/button.svg",alt:"Deploy on Railway"})})}),` |
|
| 30 | + | `,s.jsxs(i.h3,{id:"docker",children:["Docker",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#docker",children:s.jsx(i.div,{"data-autolink-icon":!0})})]}),` |
|
| 31 | + | `,s.jsx(s.Fragment,{children:s.jsx(i.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(i.code,{children:[s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:"cd"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" apps/shrink"})]}),` |
|
| 32 | + | `,s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"docker"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" compose"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" up"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -d"})]})]})})}),` |
|
| 33 | + | `,s.jsxs(i.p,{children:["This will start Shrink on port ",s.jsx(i.code,{children:"3000"}),"."]}),` |
|
| 34 | + | `,s.jsxs(i.h3,{id:"binary",children:["Binary",s.jsx(i.a,{"aria-hidden":"true",tabIndex:"-1",href:"#binary",children:s.jsx(i.div,{"data-autolink-icon":!0})})]}),` |
|
| 35 | + | `,s.jsx(s.Fragment,{children:s.jsx(i.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsx(i.code,{children:s.jsxs(i.span,{className:"line",children:[s.jsx(i.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" build"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" --release"}),s.jsx(i.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(i.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" shrink"})]})})})}),` |
|
| 36 | + | `,s.jsx(i.p,{children:"The resulting binary is self-contained. Copy it to your server and run it directly."})]})}function l(e={}){const{wrapper:i}={...n(),...e.components};return i?s.jsx(i,{...e,children:s.jsx(r,{...e})}):r(e)}export{l as default,d as frontmatter}; |
| 1 | + | import{u as n,j as e}from"./index-DO6OtFZH.js";const a={title:"Sipp",description:"undefined"};function r(i){const s={a:"a",aside:"aside",code:"code",div:"div",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",img:"img",li:"li",p:"p",pre:"pre",span:"span",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...n(),...i.components};return e.jsxs(e.Fragment,{children:[e.jsx(s.header,{children:e.jsxs(s.h1,{id:"sipp",children:["Sipp",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#sipp",children:e.jsx(s.div,{"data-autolink-icon":!0})})]})}),` |
|
| 2 | + | `,e.jsx(s.p,{children:"Minimal code sharing"}),` |
|
| 3 | + | `,e.jsxs(s.h2,{id:"overview",children:["Overview",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#overview",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 4 | + | `,e.jsx(s.p,{children:"A single binary for code sharing with a web server and interactive TUI."}),` |
|
| 5 | + | `,e.jsxs(s.ul,{children:[` |
|
| 6 | + | `,e.jsx(s.li,{children:"Create snippets and share on the web"}),` |
|
| 7 | + | `,e.jsxs(s.li,{children:["Raw output for CLI tools -- ",e.jsx(s.code,{children:"curl"}),", ",e.jsx(s.code,{children:"wget"}),", and ",e.jsx(s.code,{children:"httpie"})," get plain text automatically"]}),` |
|
| 8 | + | `,e.jsx(s.li,{children:"Interactive TUI with authenticated access for snippet management"}),` |
|
| 9 | + | `,e.jsx(s.li,{children:"Minimal, fast, and low memory consumption"}),` |
|
| 10 | + | `]}),` |
|
| 11 | + | `,e.jsx(s.aside,{"data-callout":"warning",children:e.jsxs(s.p,{children:["A small demo instance runs at ",e.jsx(s.a,{href:"https://sipp.so",children:"sipp.so"}),". All snippets created there are public and might be deleted at any time; host your own instance with your own API key for personal use!"]})}),` |
|
| 12 | + | `,e.jsxs(s.h2,{id:"quickstart",children:["Quickstart",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#quickstart",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 13 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsxs(s.code,{children:[e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" install"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" sipp-so"})]}),` |
|
| 14 | + | `,e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"sipp"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" --help"})]})]})})}),` |
|
| 15 | + | `,e.jsx(s.p,{children:"Start a server and create a snippet:"}),` |
|
| 16 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsx(s.code,{children:e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"sipp"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" server"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" --port"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" 3000"})]})})})}),` |
|
| 17 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsxs(s.code,{children:[e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#BDC4CC","--shiki-dark":"#BDC4CC"},children:"# Path to file"})}),` |
|
| 18 | + | `,e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"sipp"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" path/to/file.rs"})]}),` |
|
| 19 | + | `,e.jsx(s.span,{className:"line","data-empty-line":!0,children:" "}),` |
|
| 20 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#BDC4CC","--shiki-dark":"#BDC4CC"},children:"# Or use the interactive TUI"})}),` |
|
| 21 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"sipp"})})]})})}),` |
|
| 22 | + | `,e.jsxs(s.h3,{id:"install",children:["Install",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#install",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 23 | + | `,e.jsx(s.p,{children:"Sipp can be installed several ways:"}),` |
|
| 24 | + | `,e.jsxs(s.h4,{id:"homebrew",children:["Homebrew",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#homebrew",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 25 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsx(s.code,{children:e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"brew"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" install"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" stevedylandev/tap/sipp-so"})]})})})}),` |
|
| 26 | + | `,e.jsxs(s.h4,{id:"cargo",children:["Cargo",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#cargo",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 27 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsx(s.code,{children:e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" install"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" sipp-so"})]})})})}),` |
|
| 28 | + | `,e.jsxs(s.h4,{id:"releases",children:["Releases",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#releases",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 29 | + | `,e.jsxs(s.p,{children:["Visit the ",e.jsx(s.a,{href:"https://github.com/stevedylandev/sipp/releases",children:"releases"})," page for binaries and install scripts."]}),` |
|
| 30 | + | `,e.jsxs(s.h2,{id:"cli",children:["CLI",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#cli",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 31 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsx(s.code,{children:e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"sipp ["}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:"OPTIONS"}),e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"] ["}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:"FILE"}),e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"] ["}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:"COMMAND"}),e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"]"})]})})})}),` |
|
| 32 | + | `,e.jsxs(s.h3,{id:"commands",children:["Commands",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#commands",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 33 | + | `,e.jsxs(s.table,{children:[e.jsx(s.thead,{children:e.jsxs(s.tr,{children:[e.jsx(s.th,{children:"Command"}),e.jsx(s.th,{children:"Description"})]})}),e.jsxs(s.tbody,{children:[e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"server"})}),e.jsx(s.td,{children:"Start the web server"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"tui"})}),e.jsx(s.td,{children:"Launch the interactive TUI"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"auth"})}),e.jsx(s.td,{children:"Save remote URL and API key to config file"})]})]})]}),` |
|
| 34 | + | `,e.jsxs(s.h3,{id:"arguments",children:["Arguments",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#arguments",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 35 | + | `,e.jsxs(s.table,{children:[e.jsx(s.thead,{children:e.jsxs(s.tr,{children:[e.jsx(s.th,{children:"Argument"}),e.jsx(s.th,{children:"Description"})]})}),e.jsx(s.tbody,{children:e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"[FILE]"})}),e.jsx(s.td,{children:"File path to create a snippet from"})]})})]}),` |
|
| 36 | + | `,e.jsxs(s.h3,{id:"options",children:["Options",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#options",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 37 | + | `,e.jsxs(s.table,{children:[e.jsx(s.thead,{children:e.jsxs(s.tr,{children:[e.jsx(s.th,{children:"Option"}),e.jsx(s.th,{children:"Description"})]})}),e.jsxs(s.tbody,{children:[e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"-r, --remote <URL>"})}),e.jsxs(s.td,{children:["Remote server URL (env: ",e.jsx(s.code,{children:"SIPP_REMOTE_URL"}),")"]})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"-k, --api-key <KEY>"})}),e.jsxs(s.td,{children:["API key for authenticated operations (env: ",e.jsx(s.code,{children:"SIPP_API_KEY"}),")"]})]})]})]}),` |
|
| 38 | + | `,e.jsxs(s.h2,{id:"server",children:["Server",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#server",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 39 | + | `,e.jsx(s.p,{children:"Sipp includes a built-in web server powered by Axum. Start it with:"}),` |
|
| 40 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsx(s.code,{children:e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"sipp"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" server"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" --port"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" 3000"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" --host"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" localhost"})]})})})}),` |
|
| 41 | + | `,e.jsxs(s.h3,{id:"environment-variables",children:["Environment Variables",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#environment-variables",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 42 | + | `,e.jsxs(s.table,{children:[e.jsx(s.thead,{children:e.jsxs(s.tr,{children:[e.jsx(s.th,{children:"Variable"}),e.jsx(s.th,{children:"Description"})]})}),e.jsxs(s.tbody,{children:[e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"SIPP_API_KEY"})}),e.jsx(s.td,{children:"API key for protecting endpoints"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"SIPP_AUTH_ENDPOINTS"})}),e.jsxs(s.td,{children:["Comma-separated list of endpoints requiring auth: ",e.jsx(s.code,{children:"api_list"}),", ",e.jsx(s.code,{children:"api_create"}),", ",e.jsx(s.code,{children:"api_get"}),", ",e.jsx(s.code,{children:"api_delete"}),", ",e.jsx(s.code,{children:"all"}),", or ",e.jsx(s.code,{children:"none"})," (defaults to ",e.jsx(s.code,{children:"api_delete,api_list"}),")"]})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"SIPP_MAX_CONTENT_SIZE"})}),e.jsxs(s.td,{children:["Maximum snippet content size in bytes (defaults to ",e.jsx(s.code,{children:"512000"})," / 500 KB)"]})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"SIPP_DB_PATH"})}),e.jsxs(s.td,{children:["Custom path for the SQLite database file (defaults to ",e.jsx(s.code,{children:"sipp.sqlite"}),")"]})]})]})]}),` |
|
| 43 | + | `,e.jsxs(s.h3,{id:"api-endpoints",children:["API Endpoints",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#api-endpoints",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 44 | + | `,e.jsxs(s.table,{children:[e.jsx(s.thead,{children:e.jsxs(s.tr,{children:[e.jsx(s.th,{children:"Method"}),e.jsx(s.th,{children:"Endpoint"}),e.jsx(s.th,{children:"Description"})]})}),e.jsxs(s.tbody,{children:[e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"GET"})}),e.jsx(s.td,{children:e.jsx(s.code,{children:"/api/snippets"})}),e.jsx(s.td,{children:"List all snippets"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"POST"})}),e.jsx(s.td,{children:e.jsx(s.code,{children:"/api/snippets"})}),e.jsxs(s.td,{children:["Create a snippet (",e.jsx(s.code,{children:'{"name": "...", "content": "..."}'}),")"]})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"GET"})}),e.jsx(s.td,{children:e.jsx(s.code,{children:"/api/snippets/{short_id}"})}),e.jsx(s.td,{children:"Get a snippet by ID"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"PUT"})}),e.jsx(s.td,{children:e.jsx(s.code,{children:"/api/snippets/{short_id}"})}),e.jsx(s.td,{children:"Update a snippet"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"DELETE"})}),e.jsx(s.td,{children:e.jsx(s.code,{children:"/api/snippets/{short_id}"})}),e.jsx(s.td,{children:"Delete a snippet by ID"})]})]})]}),` |
|
| 45 | + | `,e.jsxs(s.p,{children:["Authenticated endpoints require an ",e.jsx(s.code,{children:"x-api-key"})," header."]}),` |
|
| 46 | + | `,e.jsxs(s.h3,{id:"raw-output-for-cli-tools",children:["Raw Output for CLI Tools",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#raw-output-for-cli-tools",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 47 | + | `,e.jsxs(s.p,{children:["When you access a snippet URL (",e.jsx(s.code,{children:"/s/{short_id}"}),") with ",e.jsx(s.code,{children:"curl"}),", ",e.jsx(s.code,{children:"wget"}),", or ",e.jsx(s.code,{children:"httpie"}),", the server returns the raw content as plain text instead of HTML:"]}),` |
|
| 48 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsx(s.code,{children:e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"curl"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" https://sipp.so/s/abc123"})]})})})}),` |
|
| 49 | + | `,e.jsxs(s.h2,{id:"tui",children:["TUI",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#tui",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 50 | + | `,e.jsx(s.p,{children:"The Sipp TUI makes it easy to create, copy, share, and manage your snippets either locally or remotely."}),` |
|
| 51 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsxs(s.code,{children:[e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#BDC4CC","--shiki-dark":"#BDC4CC"},children:"# Launch TUI (default behavior when no file argument is given)"})}),` |
|
| 52 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"sipp"})}),` |
|
| 53 | + | `,e.jsx(s.span,{className:"line","data-empty-line":!0,children:" "}),` |
|
| 54 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#BDC4CC","--shiki-dark":"#BDC4CC"},children:"# Or explicitly"})}),` |
|
| 55 | + | `,e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"sipp"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" tui"})]}),` |
|
| 56 | + | `,e.jsx(s.span,{className:"line","data-empty-line":!0,children:" "}),` |
|
| 57 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#BDC4CC","--shiki-dark":"#BDC4CC"},children:"# With remote options"})}),` |
|
| 58 | + | `,e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"sipp"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -r"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" https://sipp.so"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -k"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" your-api-key"})]})]})})}),` |
|
| 59 | + | `,e.jsxs(s.h3,{id:"local-access",children:["Local Access",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#local-access",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 60 | + | `,e.jsxs(s.p,{children:["If you are running ",e.jsx(s.code,{children:"sipp"})," in the same directory as the ",e.jsx(s.code,{children:"sipp.sqlite"})," file created by the server instance, the TUI will automatically access the database locally."]}),` |
|
| 61 | + | `,e.jsxs(s.h3,{id:"remote-access",children:["Remote Access",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#remote-access",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 62 | + | `,e.jsx(s.p,{children:"To access a remote instance:"}),` |
|
| 63 | + | `,e.jsxs(s.ul,{children:[` |
|
| 64 | + | `,e.jsxs(s.li,{children:["Set the ",e.jsx(s.code,{children:"SIPP_API_KEY"})," variable in your server instance"]}),` |
|
| 65 | + | `,e.jsxs(s.li,{children:["Run ",e.jsx(s.code,{children:"sipp auth"})," to enter your server URL and API key, stored under ",e.jsx(s.code,{children:"$HOME/.config/sipp"})]}),` |
|
| 66 | + | `]}),` |
|
| 67 | + | `,e.jsxs(s.h3,{id:"keybindings",children:["Keybindings",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#keybindings",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 68 | + | `,e.jsxs(s.table,{children:[e.jsx(s.thead,{children:e.jsxs(s.tr,{children:[e.jsx(s.th,{children:"Key"}),e.jsx(s.th,{children:"Action"})]})}),e.jsxs(s.tbody,{children:[e.jsxs(s.tr,{children:[e.jsxs(s.td,{children:[e.jsx(s.code,{children:"j"}),"/",e.jsx(s.code,{children:"Down"})]}),e.jsx(s.td,{children:"Move down / Scroll down"})]}),e.jsxs(s.tr,{children:[e.jsxs(s.td,{children:[e.jsx(s.code,{children:"k"}),"/",e.jsx(s.code,{children:"Up"})]}),e.jsx(s.td,{children:"Move up / Scroll up"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"Enter"})}),e.jsx(s.td,{children:"Focus content pane"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"Esc"})}),e.jsx(s.td,{children:"Back / Quit"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"y"})}),e.jsx(s.td,{children:"Copy snippet content"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"Y"})}),e.jsx(s.td,{children:"Copy snippet link"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"o"})}),e.jsx(s.td,{children:"Open in browser"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"e"})}),e.jsx(s.td,{children:"Edit snippet"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"d"})}),e.jsx(s.td,{children:"Delete snippet"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"c"})}),e.jsx(s.td,{children:"Create snippet"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"/"})}),e.jsx(s.td,{children:"Search snippets"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"r"})}),e.jsx(s.td,{children:"Refresh snippets (remote only)"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"q"})}),e.jsx(s.td,{children:"Quit"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"?"})}),e.jsx(s.td,{children:"Toggle help"})]})]})]}),` |
|
| 69 | + | `,e.jsxs(s.h2,{id:"structure",children:["Structure",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#structure",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 70 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsxs(s.code,{children:[e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"sipp/"})}),` |
|
| 71 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── src/"})}),` |
|
| 72 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── main.rs # CLI argument parsing and entry point"})}),` |
|
| 73 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── lib.rs # Library exports"})}),` |
|
| 74 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── server.rs # Axum web server, routes, and templates"})}),` |
|
| 75 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── tui.rs # Interactive terminal UI"})}),` |
|
| 76 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── db.rs # SQLite database layer"})}),` |
|
| 77 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── backend.rs # Local/remote backend abstraction"})}),` |
|
| 78 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── config.rs # Config file management"})}),` |
|
| 79 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ └── highlight.rs # Syntax highlighting with custom themes"})}),` |
|
| 80 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── templates/ # Askama HTML templates"})}),` |
|
| 81 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── static/ # Fonts, favicons, and styles"})}),` |
|
| 82 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── Dockerfile"})}),` |
|
| 83 | + | `,e.jsx(s.span,{className:"line",children:e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"└── docker-compose.yml"})})]})})}),` |
|
| 84 | + | `,e.jsxs(s.h2,{id:"deployment",children:["Deployment",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#deployment",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 85 | + | `,e.jsxs(s.h3,{id:"railway",children:["Railway",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#railway",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 86 | + | `,e.jsx(s.p,{children:e.jsx(s.a,{href:"https://railway.com/deploy/Axcf_D?referralCode=JGcIp6",children:e.jsx(s.img,{src:"https://railway.com/button.svg",alt:"Deploy on Railway"})})}),` |
|
| 87 | + | `,e.jsxs(s.h3,{id:"docker",children:["Docker",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#docker",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 88 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsx(s.code,{children:e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"SIPP_API_KEY"}),e.jsx(s.span,{style:{color:"#FF9492","--shiki-dark":"#FF9492"},children:"="}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:"your-secret-key"}),e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:" docker"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" compose"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" up"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -d"})]})})})}),` |
|
| 89 | + | `,e.jsxs(s.h3,{id:"binary",children:["Binary",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#binary",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 90 | + | `,e.jsx(e.Fragment,{children:e.jsx(s.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:e.jsx(s.code,{children:e.jsxs(s.span,{className:"line",children:[e.jsx(s.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" build"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" --release"}),e.jsx(s.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),e.jsx(s.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" sipp"})]})})})}),` |
|
| 91 | + | `,e.jsx(s.p,{children:"The resulting binary is self-contained with all assets embedded. Copy it to your server with your environment variables configured and run it directly."})]})}function l(i={}){const{wrapper:s}={...n(),...i.components};return s?e.jsx(s,{...i,children:e.jsx(r,{...i})}):r(i)}export{l as default,a as frontmatter}; |
| 1 | + | import{u as a,j as s}from"./index-DO6OtFZH.js";const l={title:"Skills",description:"undefined"};function r(i){const e={a:"a",code:"code",div:"div",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",span:"span",ul:"ul",...a(),...i.components};return s.jsxs(s.Fragment,{children:[s.jsx(e.header,{children:s.jsxs(e.h1,{id:"skills",children:["Skills",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#skills",children:s.jsx(e.div,{"data-autolink-icon":!0})})]})}),` |
|
| 2 | + | `,s.jsxs(e.p,{children:["Andromeda apps are scaffolded using ",s.jsx(e.a,{href:"https://claude.ai/code",children:"Claude Code"})," with a custom skill called ",s.jsx(e.code,{children:"rust-crud"}),". This page explains how to use it to build your own apps in the same style."]}),` |
|
| 3 | + | `,s.jsxs(e.h2,{id:"what-is-rust-crud",children:["What is rust-crud?",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#what-is-rust-crud",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 4 | + | `,s.jsxs(e.p,{children:[s.jsx(e.code,{children:"rust-crud"})," is a Claude Code skill that scaffolds a complete Rust CRUD web application matching the Andromeda stack:"]}),` |
|
| 5 | + | `,s.jsxs(e.ul,{children:[` |
|
| 6 | + | `,s.jsx(e.li,{children:"Axum web server with routing"}),` |
|
| 7 | + | `,s.jsx(e.li,{children:"SQLite database with rusqlite"}),` |
|
| 8 | + | `,s.jsx(e.li,{children:"Askama HTML templates"}),` |
|
| 9 | + | `,s.jsx(e.li,{children:"API key authentication"}),` |
|
| 10 | + | `,s.jsx(e.li,{children:"Embedded static assets via rust-embed"}),` |
|
| 11 | + | `,s.jsx(e.li,{children:"Dockerfile and docker-compose.yml for deployment"}),` |
|
| 12 | + | `]}),` |
|
| 13 | + | `,s.jsxs(e.h2,{id:"using-the-skill",children:["Using the Skill",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#using-the-skill",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 14 | + | `,s.jsx(e.p,{children:"In Claude Code, invoke the skill when you want to create a new app:"}),` |
|
| 15 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsx(e.code,{children:s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"/rust-crud"})})})})}),` |
|
| 16 | + | `,s.jsx(e.p,{children:"Describe what you want to build and the skill will generate a complete, working app that follows the same patterns as every other Andromeda app."}),` |
|
| 17 | + | `,s.jsxs(e.h2,{id:"building-your-own-app",children:["Building Your Own App",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#building-your-own-app",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 18 | + | `,s.jsx(e.p,{children:"If you want to add a new app to the workspace manually, follow these steps:"}),` |
|
| 19 | + | `,s.jsxs(e.h3,{id:"1-create-the-app-directory",children:["1. Create the app directory",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#1-create-the-app-directory",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 20 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"mkdir"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" apps/my-app/src"})]}),` |
|
| 21 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"mkdir"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" apps/my-app/templates"})]}),` |
|
| 22 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"mkdir"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" apps/my-app/static"})]})]})})}),` |
|
| 23 | + | `,s.jsxs(e.h3,{id:"2-add-to-workspace",children:["2. Add to workspace",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#2-add-to-workspace",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 24 | + | `,s.jsxs(e.p,{children:["Add your app to the root ",s.jsx(e.code,{children:"Cargo.toml"})," workspace members:"]}),` |
|
| 25 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"["}),s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"workspace"}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"]"})]}),` |
|
| 26 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"members = ["})}),` |
|
| 27 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:' "apps/my-app"'}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:","})]}),` |
|
| 28 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#BDC4CC","--shiki-dark":"#BDC4CC"},children:" # ...existing apps"})}),` |
|
| 29 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"]"})})]})})}),` |
|
| 30 | + | `,s.jsxs(e.h3,{id:"3-set-up-cargotoml",children:["3. Set up Cargo.toml",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#3-set-up-cargotoml",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 31 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"["}),s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"package"}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"]"})]}),` |
|
| 32 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"name = "}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"my-app"'})]}),` |
|
| 33 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"version = "}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"0.1.0"'})]}),` |
|
| 34 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"edition = "}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"2021"'})]}),` |
|
| 35 | + | `,s.jsx(e.span,{className:"line","data-empty-line":!0,children:" "}),` |
|
| 36 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"["}),s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"dependencies"}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"]"})]}),` |
|
| 37 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"axum = "}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"0.8"'})]}),` |
|
| 38 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"tokio = { version = "}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"1"'}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:", features = ["}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"full"'}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"] }"})]}),` |
|
| 39 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"rusqlite = { version = "}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"0.32"'}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:", features = ["}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"bundled"'}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"] }"})]}),` |
|
| 40 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"askama = "}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"0.12"'})]}),` |
|
| 41 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"askama_axum = "}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"0.4"'})]}),` |
|
| 42 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"rust-embed = "}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"8"'})]}),` |
|
| 43 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"tower-http = { version = "}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"0.6"'}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:", features = ["}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"cors"'}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"] }"})]}),` |
|
| 44 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"serde = { version = "}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"1"'}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:", features = ["}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"derive"'}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"] }"})]}),` |
|
| 45 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"dotenvy = "}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"0.15"'})]})]})})}),` |
|
| 46 | + | `,s.jsxs(e.h3,{id:"4-follow-the-pattern",children:["4. Follow the pattern",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#4-follow-the-pattern",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 47 | + | `,s.jsxs(e.p,{children:["Use the ",s.jsx(e.a,{href:"/diy/stack",children:"Stack"})," page as a reference for how to structure your ",s.jsx(e.code,{children:"main.rs"}),", ",s.jsx(e.code,{children:"server.rs"}),", and ",s.jsx(e.code,{children:"db.rs"})," files. Look at any existing app in ",s.jsx(e.code,{children:"apps/"})," for a working example."]}),` |
|
| 48 | + | `,s.jsxs(e.h3,{id:"5-build-and-run",children:["5. Build and run",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#5-build-and-run",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 49 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsx(e.code,{children:s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"cargo"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" run"}),s.jsx(e.span,{style:{color:"#91CBFF","--shiki-dark":"#91CBFF"},children:" -p"}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:" my-app"})]})})})})]})}function d(i={}){const{wrapper:e}={...a(),...i.components};return e?s.jsx(e,{...i,children:s.jsx(r,{...i})}):r(i)}export{d as default,l as frontmatter}; |
| 1 | + | import{u as n,j as s}from"./index-DO6OtFZH.js";const l={title:"Stack",description:"undefined"};function a(i){const e={a:"a",code:"code",div:"div",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",span:"span",ul:"ul",...n(),...i.components};return s.jsxs(s.Fragment,{children:[s.jsx(e.header,{children:s.jsxs(e.h1,{id:"stack",children:["Stack",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#stack",children:s.jsx(e.div,{"data-autolink-icon":!0})})]})}),` |
|
| 2 | + | `,s.jsx(e.p,{children:"Every app in Andromeda is built on the same Rust stack. This page covers the core dependencies and how they fit together."}),` |
|
| 3 | + | `,s.jsxs(e.h2,{id:"core-dependencies",children:["Core Dependencies",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#core-dependencies",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 4 | + | `,s.jsxs(e.h3,{id:"axum",children:["Axum",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#axum",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 5 | + | `,s.jsxs(e.p,{children:[s.jsx(e.a,{href:"https://github.com/tokio-rs/axum",children:"Axum"})," is the web framework powering every app. It provides routing, request extraction, middleware, and response handling. All apps follow a similar pattern:"]}),` |
|
| 6 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FF9492","--shiki-dark":"#FF9492"},children:"let"}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:" app "}),s.jsx(e.span,{style:{color:"#FF9492","--shiki-dark":"#FF9492"},children:"="}),s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:" Router"}),s.jsx(e.span,{style:{color:"#FF9492","--shiki-dark":"#FF9492"},children:"::"}),s.jsx(e.span,{style:{color:"#DBB7FF","--shiki-dark":"#DBB7FF"},children:"new"}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"()"})]}),` |
|
| 7 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FF9492","--shiki-dark":"#FF9492"},children:" ."}),s.jsx(e.span,{style:{color:"#DBB7FF","--shiki-dark":"#DBB7FF"},children:"route"}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"("}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"/"'}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:", "}),s.jsx(e.span,{style:{color:"#DBB7FF","--shiki-dark":"#DBB7FF"},children:"get"}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"(index))"})]}),` |
|
| 8 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FF9492","--shiki-dark":"#FF9492"},children:" ."}),s.jsx(e.span,{style:{color:"#DBB7FF","--shiki-dark":"#DBB7FF"},children:"route"}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"("}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:'"/api/items"'}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:", "}),s.jsx(e.span,{style:{color:"#DBB7FF","--shiki-dark":"#DBB7FF"},children:"post"}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"(create_item))"})]}),` |
|
| 9 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FF9492","--shiki-dark":"#FF9492"},children:" ."}),s.jsx(e.span,{style:{color:"#DBB7FF","--shiki-dark":"#DBB7FF"},children:"with_state"}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"(app_state);"})]})]})})}),` |
|
| 10 | + | `,s.jsxs(e.h3,{id:"sqlite-rusqlite",children:["SQLite (rusqlite)",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#sqlite-rusqlite",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 11 | + | `,s.jsxs(e.p,{children:[s.jsx(e.a,{href:"https://github.com/rusqlite/rusqlite",children:"rusqlite"})," provides the storage layer. Each app creates its own SQLite database file, keeping data local and portable. No external database server needed."]}),` |
|
| 12 | + | `,s.jsxs(e.h3,{id:"askama",children:["Askama",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#askama",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 13 | + | `,s.jsxs(e.p,{children:[s.jsx(e.a,{href:"https://github.com/djc/askama",children:"Askama"})," handles HTML templating with compile-time checked templates. Templates live in a ",s.jsx(e.code,{children:"templates/"})," directory and are type-safe Rust structs:"]}),` |
|
| 14 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"#[derive("}),s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"Template"}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:")]"})]}),` |
|
| 15 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"#[template(path "}),s.jsx(e.span,{style:{color:"#FF9492","--shiki-dark":"#FF9492"},children:"="}),s.jsx(e.span,{style:{color:"#ADDCFF","--shiki-dark":"#ADDCFF"},children:' "index.html"'}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:")]"})]}),` |
|
| 16 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#FF9492","--shiki-dark":"#FF9492"},children:"struct"}),s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:" IndexTemplate"}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:" {"})]}),` |
|
| 17 | + | `,s.jsxs(e.span,{className:"line",children:[s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:" items"}),s.jsx(e.span,{style:{color:"#FF9492","--shiki-dark":"#FF9492"},children:":"}),s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:" Vec"}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"<"}),s.jsx(e.span,{style:{color:"#FFB757","--shiki-dark":"#FFB757"},children:"Item"}),s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:">,"})]}),` |
|
| 18 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"}"})})]})})}),` |
|
| 19 | + | `,s.jsxs(e.h3,{id:"rust-embed",children:["rust-embed",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#rust-embed",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 20 | + | `,s.jsxs(e.p,{children:[s.jsx(e.a,{href:"https://github.com/pyrossh/rust-embed",children:"rust-embed"})," embeds static assets (CSS, fonts, images) directly into the binary at compile time. This is what makes each app a single, self-contained binary with no external file dependencies."]}),` |
|
| 21 | + | `,s.jsxs(e.h3,{id:"tokio",children:["Tokio",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#tokio",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 22 | + | `,s.jsxs(e.p,{children:[s.jsx(e.a,{href:"https://tokio.rs",children:"Tokio"})," provides the async runtime that Axum runs on."]}),` |
|
| 23 | + | `,s.jsxs(e.h2,{id:"shared-crate-andromeda-auth",children:["Shared Crate: andromeda-auth",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#shared-crate-andromeda-auth",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 24 | + | `,s.jsxs(e.p,{children:["The ",s.jsx(e.code,{children:"andromeda-auth"})," crate provides session-based password authentication used across apps that require login. It handles:"]}),` |
|
| 25 | + | `,s.jsxs(e.ul,{children:[` |
|
| 26 | + | `,s.jsx(e.li,{children:"Constant-time password verification"}),` |
|
| 27 | + | `,s.jsx(e.li,{children:"Session cookie management"}),` |
|
| 28 | + | `,s.jsxs(e.li,{children:["Secure cookie configuration via ",s.jsx(e.code,{children:"COOKIE_SECURE"})," env var"]}),` |
|
| 29 | + | `]}),` |
|
| 30 | + | `,s.jsxs(e.h2,{id:"app-pattern",children:["App Pattern",s.jsx(e.a,{"aria-hidden":"true",tabIndex:"-1",href:"#app-pattern",children:s.jsx(e.div,{"data-autolink-icon":!0})})]}),` |
|
| 31 | + | `,s.jsx(e.p,{children:"Every app follows a consistent structure:"}),` |
|
| 32 | + | `,s.jsx(s.Fragment,{children:s.jsx(e.pre,{className:"shiki shiki-themes github-dark-high-contrast github-dark-high-contrast",style:{backgroundColor:"#0a0c10","--shiki-dark-bg":"#0a0c10",color:"#f0f3f6","--shiki-dark":"#f0f3f6"},tabIndex:"0",children:s.jsxs(e.code,{children:[s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"app/"})}),` |
|
| 33 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── src/"})}),` |
|
| 34 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── main.rs # Entry point, env vars, starts server"})}),` |
|
| 35 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── server.rs # Axum routes and handlers"})}),` |
|
| 36 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ ├── db.rs # SQLite database layer"})}),` |
|
| 37 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"│ └── auth.rs # Authentication (if needed)"})}),` |
|
| 38 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── templates/ # Askama HTML templates"})}),` |
|
| 39 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── static/ # Fonts, favicons, styles"})}),` |
|
| 40 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"├── Dockerfile"})}),` |
|
| 41 | + | `,s.jsx(e.span,{className:"line",children:s.jsx(e.span,{style:{color:"#F0F3F6","--shiki-dark":"#F0F3F6"},children:"└── docker-compose.yml"})})]})})}),` |
|
| 42 | + | `,s.jsx(e.p,{children:"This consistency means once you understand one app, you can navigate any of them."})]})}function d(i={}){const{wrapper:e}={...n(),...i.components};return e?s.jsx(e,{...i,children:s.jsx(a,{...i})}):a(i)}export{d as default,l as frontmatter}; |
| 1 | + | @layer base;:root{--vocs-color_white: rgba(255 255 255 / 100%);--vocs-color_black: rgba(0 0 0 / 100%);--vocs-color_background: rgba(255 255 255 / 100%);--vocs-color_background2: #f9f9f9;--vocs-color_background3: #f6f6f6;--vocs-color_background4: #f0f0f0;--vocs-color_background5: #e8e8e8;--vocs-color_backgroundAccent: #0588f0;--vocs-color_backgroundAccentHover: #0d74ce;--vocs-color_backgroundAccentText: rgba(255 255 255 / 100%);--vocs-color_backgroundBlueTint: #f4faff;--vocs-color_backgroundDark: #f9f9f9;--vocs-color_backgroundDarkTint: #f0f0f0;--vocs-color_backgroundGreenTint: #00a32f0b;--vocs-color_backgroundGreenTint2: #00a43319;--vocs-color_backgroundIrisTint: #0000ff07;--vocs-color_backgroundRedTint: #ff000008;--vocs-color_backgroundRedTint2: #f3000d14;--vocs-color_backgroundYellowTint: #f4dd0016;--vocs-color_border: #ececec;--vocs-color_border2: #cecece;--vocs-color_borderAccent: #0090ff;--vocs-color_borderBlue: #009eff2a;--vocs-color_borderGreen: #019c393b;--vocs-color_borderIris: #dadcff;--vocs-color_borderRed: #ff000824;--vocs-color_borderYellow: #ffd5008f;--vocs-color_heading: #202020;--vocs-color_inverted: rgba(0 0 0 / 100%);--vocs-color_shadow: #0000000f;--vocs-color_shadow2: #00000006;--vocs-color_text: #4c4c4c;--vocs-color_text2: #646464;--vocs-color_text3: #838383;--vocs-color_text4: #bbbbbb;--vocs-color_textAccent: #0588f0;--vocs-color_textAccentHover: #0d74ce;--vocs-color_textBlue: #0588f0;--vocs-color_textBlueHover: #0d74ce;--vocs-color_textGreen: #218358;--vocs-color_textGreenHover: #193b2d;--vocs-color_textHover: rgba(0 0 0 / 100%);--vocs-color_textIris: #5753c6;--vocs-color_textIrisHover: #272962;--vocs-color_textRed: #ce2c31;--vocs-color_textRedHover: #641723;--vocs-color_textYellow: #9e6c00;--vocs-color_textYellowHover: #473b1f;--vocs-color_title: #202020}:root.dark{--vocs-color_white: rgba(255 255 255 / 100%);--vocs-color_black: rgba(0 0 0 / 100%);--vocs-color_background: #121113;--vocs-color_background2: #1a191b;--vocs-color_background3: #1a191b;--vocs-color_background4: #232225;--vocs-color_background5: #2b292d;--vocs-color_backgroundAccent: #0090ff;--vocs-color_backgroundAccentHover: #3b9eff;--vocs-color_backgroundAccentText: rgba(255 255 255 / 100%);--vocs-color_backgroundBlueTint: #008ff519;--vocs-color_backgroundDark: #0e0d0f;--vocs-color_backgroundDarkTint: #1a191b;--vocs-color_backgroundGreenTint: #00a43319;--vocs-color_backgroundGreenTint2: #00a83829;--vocs-color_backgroundIrisTint: #000bff19;--vocs-color_backgroundRedTint: #f3000d14;--vocs-color_backgroundRedTint2: #ff000824;--vocs-color_backgroundYellowTint: #f4dd0016;--vocs-color_border: #2b292d;--vocs-color_border2: #3c393f;--vocs-color_borderAccent: #3b9eff;--vocs-color_borderBlue: #009eff2a;--vocs-color_borderGreen: #019c393b;--vocs-color_borderIris: #303374;--vocs-color_borderRed: #ff000824;--vocs-color_borderYellow: #f4dd0016;--vocs-color_heading: rgba(255 255 255 / 100%);--vocs-color_inverted: rgba(255 255 255 / 100%);--vocs-color_shadow: #00000000;--vocs-color_shadow2: rgba(0, 0, 0, .05);--vocs-color_text: rgba(255, 255, 255, .8);--vocs-color_text2: rgba(255, 255, 255, .7);--vocs-color_text3: rgba(255, 255, 255, .6);--vocs-color_text4: rgba(255, 255, 255, .5);--vocs-color_textAccent: #3b9eff;--vocs-color_textAccentHover: #0090ff;--vocs-color_textBlue: #70b8ff;--vocs-color_textBlueHover: #3b9eff;--vocs-color_textGreen: #3dd68c;--vocs-color_textGreenHover: #33b074;--vocs-color_textHover: rgba(255 255 255 / 100%);--vocs-color_textIris: #b1a9ff;--vocs-color_textIrisHover: #6e6ade;--vocs-color_textRed: #ff9592;--vocs-color_textRedHover: #ec5d5e;--vocs-color_textYellow: #f5e147;--vocs-color_textYellowHover: #e2a336;--vocs-color_title: rgba(255 255 255 / 100%)}:root{--vocs-color_blockquoteBorder: var(--vocs-color_border);--vocs-color_blockquoteText: var(--vocs-color_text2);--vocs-color_dangerBackground: var(--vocs-color_backgroundRedTint);--vocs-color_dangerBorder: var(--vocs-color_borderRed);--vocs-color_dangerText: var(--vocs-color_textRed);--vocs-color_dangerTextHover: var(--vocs-color_textRedHover);--vocs-color_infoBackground: var(--vocs-color_backgroundBlueTint);--vocs-color_infoBorder: var(--vocs-color_borderBlue);--vocs-color_infoText: var(--vocs-color_textBlue);--vocs-color_infoTextHover: var(--vocs-color_textBlueHover);--vocs-color_noteBackground: var(--vocs-color_background2);--vocs-color_noteBorder: var(--vocs-color_border);--vocs-color_noteText: var(--vocs-color_text2);--vocs-color_successBackground: var(--vocs-color_backgroundGreenTint);--vocs-color_successBorder: var(--vocs-color_borderGreen);--vocs-color_successText: var(--vocs-color_textGreen);--vocs-color_successTextHover: var(--vocs-color_textGreenHover);--vocs-color_tipBackground: var(--vocs-color_backgroundIrisTint);--vocs-color_tipBorder: var(--vocs-color_borderIris);--vocs-color_tipText: var(--vocs-color_textIris);--vocs-color_tipTextHover: var(--vocs-color_textIrisHover);--vocs-color_warningBackground: var(--vocs-color_backgroundYellowTint);--vocs-color_warningBorder: var(--vocs-color_borderYellow);--vocs-color_warningText: var(--vocs-color_textYellow);--vocs-color_warningTextHover: var(--vocs-color_textYellowHover);--vocs-color_codeBlockBackground: var(--vocs-color_backgroundDark);--vocs-color_codeCharacterHighlightBackground: var(--vocs-color_background3);--vocs-color_codeCharacterHighlightBorder: var(--vocs-color_border);--vocs-color_codeHighlightBackground: var(--vocs-color_backgroundDarkTint);--vocs-color_codeHighlightBorder: var(--vocs-color_border2);--vocs-color_codeInlineBackground: var(--vocs-color_background2);--vocs-color_codeInlineBorder: var(--vocs-color_border);--vocs-color_codeInlineText: var(--vocs-color_textAccent);--vocs-color_codeTitleBackground: var(--vocs-color_background);--vocs-color_lineNumber: var(--vocs-color_text4);--vocs-color_hr: var(--vocs-color_border);--vocs-color_link: var(--vocs-color_textAccent);--vocs-color_linkHover: var(--vocs-color_textAccentHover);--vocs-color_searchHighlightBackground: var(--vocs-color_borderAccent);--vocs-color_searchHighlightText: var(--vocs-color_background);--vocs-color_tableBorder: var(--vocs-color_border);--vocs-color_tableHeaderBackground: var(--vocs-color_background2);--vocs-color_tableHeaderText: var(--vocs-color_text2)}:root{--vocs-borderRadius_0: 0;--vocs-borderRadius_2: 2px;--vocs-borderRadius_3: 3px;--vocs-borderRadius_4: 4px;--vocs-borderRadius_6: 6px;--vocs-borderRadius_8: 8px;--vocs-borderRadius_round: calc(infinity * 1px)}:root{--vocs-fontFamily_default: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;--vocs-fontFamily_mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}:root{--vocs-fontSize_9: .5625rem;--vocs-fontSize_11: .6875rem;--vocs-fontSize_12: .75rem;--vocs-fontSize_13: .8125rem;--vocs-fontSize_14: .875rem;--vocs-fontSize_15: .9375rem;--vocs-fontSize_16: 1rem;--vocs-fontSize_18: 1.125rem;--vocs-fontSize_20: 1.25rem;--vocs-fontSize_24: 1.5rem;--vocs-fontSize_32: 2rem;--vocs-fontSize_64: 3rem;--vocs-fontSize_root: 16px;--vocs-fontSize_h1: var(--vocs-fontSize_32);--vocs-fontSize_h2: var(--vocs-fontSize_24);--vocs-fontSize_h3: var(--vocs-fontSize_20);--vocs-fontSize_h4: var(--vocs-fontSize_18);--vocs-fontSize_h5: var(--vocs-fontSize_16);--vocs-fontSize_h6: var(--vocs-fontSize_16);--vocs-fontSize_calloutCodeBlock: .8em;--vocs-fontSize_code: .875em;--vocs-fontSize_codeBlock: var(--vocs-fontSize_14);--vocs-fontSize_lineNumber: var(--vocs-fontSize_15);--vocs-fontSize_subtitle: var(--vocs-fontSize_20);--vocs-fontSize_th: var(--vocs-fontSize_14);--vocs-fontSize_td: var(--vocs-fontSize_14)}:root{--vocs-fontWeight_regular: 300;--vocs-fontWeight_medium: 400;--vocs-fontWeight_semibold: 500}:root{--vocs-lineHeight_code: 1.75em;--vocs-lineHeight_heading: 1.5em;--vocs-lineHeight_listItem: 1.5em;--vocs-lineHeight_outlineItem: 1em;--vocs-lineHeight_paragraph: 1.75em;--vocs-lineHeight_sidebarItem: 1.375em}:root{--vocs-space_0: 0px;--vocs-space_1: 1px;--vocs-space_2: .125rem;--vocs-space_3: .1875rem;--vocs-space_4: .25rem;--vocs-space_6: .375rem;--vocs-space_8: .5rem;--vocs-space_12: .75rem;--vocs-space_14: .875rem;--vocs-space_16: 1rem;--vocs-space_18: 1.125rem;--vocs-space_20: 1.25rem;--vocs-space_22: 1.375rem;--vocs-space_24: 1.5rem;--vocs-space_28: 1.75rem;--vocs-space_32: 2rem;--vocs-space_36: 2.25rem;--vocs-space_40: 2.5rem;--vocs-space_44: 2.75rem;--vocs-space_48: 3rem;--vocs-space_56: 3.5rem;--vocs-space_64: 4rem;--vocs-space_72: 4.5rem;--vocs-space_80: 5rem}:root{--vocs-zIndex_backdrop: 69420;--vocs-zIndex_drawer: 69421;--vocs-zIndex_gutterRight: 11;--vocs-zIndex_gutterLeft: 14;--vocs-zIndex_gutterTop: 13;--vocs-zIndex_gutterTopCurtain: 12;--vocs-zIndex_popover: 69422;--vocs-zIndex_surface: 10}:root{--vocs-content_horizontalPadding: var(--vocs-space_48);--vocs-content_verticalPadding: var(--vocs-space_32);--vocs-content_width: calc(70ch + (var(--vocs-content_horizontalPadding) * 2))}:root{--vocs-outline_width: 280px}:root{--vocs-sidebar_horizontalPadding: var(--vocs-space_24);--vocs-sidebar_verticalPadding: var(--vocs-space_0);--vocs-sidebar_width: 300px}:root{--vocs-topNav_height: 60px;--vocs-topNav_horizontalPadding: var(--vocs-content_horizontalPadding);--vocs-topNav_curtainHeight: 40px}@media screen and (max-width:1080px){:root{--vocs-content_verticalPadding: var(--vocs-space_48);--vocs-content_horizontalPadding: var(--vocs-space_24);--vocs-sidebar_horizontalPadding: var(--vocs-space_16);--vocs-sidebar_verticalPadding: var(--vocs-space_16);--vocs-sidebar_width: 300px;--vocs-topNav_height: 48px}}@media screen and (max-width:720px){:root{--vocs-content_horizontalPadding: var(--vocs-space_16);--vocs-content_verticalPadding: var(--vocs-space_32)}}.vocs_Banner{background-color:var(--vocs_Banner_bannerBackgroundColor, var(--vocs-color_backgroundAccent));border-bottom:1px solid var(--vocs_Banner_bannerBackgroundColor, var(--vocs-color_borderAccent));color:var(--vocs_Banner_bannerTextColor, var(--vocs-color_backgroundAccentText));height:var(--vocs_Banner_bannerHeight, 36px);position:fixed;top:0;width:100%;z-index:var(--vocs-zIndex_gutterTop)}.vocs_Banner_content{font-size:var(--vocs-fontSize_14);overflow-x:scroll;padding-left:var(--vocs-space_8);padding-right:var(--vocs-space_8);margin-right:var(--vocs-space_24);-ms-overflow-style:none;scrollbar-width:none;white-space:pre}.vocs_Banner_content::-webkit-scrollbar{display:none}.vocs_Banner_inner{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}.vocs_Banner_closeButton{align-items:center;background-color:var(--vocs_Banner_bannerBackgroundColor, var(--vocs-color_backgroundAccent));display:flex;justify-content:center;height:100%;position:absolute;right:0;width:var(--vocs-space_24)}.vocs_Banner_content a{font-weight:400;text-underline-offset:2px;text-decoration:underline}@media screen and (max-width:1080px){.vocs_Banner{position:initial}}.vocs_DocsLayout{--vocs_DocsLayout_leftGutterWidth: max(calc((100vw - var(--vocs-content_width)) / 2), var(--vocs-sidebar_width))}.vocs_DocsLayout_content{background-color:var(--vocs-color_background);display:flex;flex-direction:column;margin-left:auto;margin-right:auto;max-width:var(--vocs-content_width);min-height:100vh}.vocs_DocsLayout_content_withSidebar{margin-left:var(--vocs_DocsLayout_leftGutterWidth);margin-right:unset}.vocs_DocsLayout_gutterLeft{background-color:var(--vocs-color_backgroundDark);justify-content:flex-end;display:flex;height:calc(100vh - var(--vocs_Banner_bannerHeight, 0px));position:fixed;top:var(--vocs_Banner_bannerHeight, 0px);width:var(--vocs_DocsLayout_leftGutterWidth);z-index:var(--vocs-zIndex_gutterLeft)}.vocs_DocsLayout_gutterTop{align-items:center;background-color:color-mix(in srgb,var(--vocs-color_background) 98%,transparent);height:var(--vocs-topNav_height);width:100vw;z-index:var(--vocs-zIndex_gutterTop)}.vocs_DocsLayout_gutterTopCurtain{display:flex;height:var(--vocs-topNav_curtainHeight);width:100vw;z-index:var(--vocs-zIndex_gutterTopCurtain)}.vocs_DocsLayout_gutterTopCurtain_hidden{background:unset;display:none}.vocs_DocsLayout_gutterRight{display:flex;height:100vh;overflow-y:auto;padding:calc(var(--vocs-content_verticalPadding) + var(--vocs-topNav_height) + var(--vocs-space_8)) var(--vocs-space_24) 0 0;position:fixed;top:var(--vocs_Banner_bannerHeight, 0px);right:0;width:calc((100vw - var(--vocs-content_width)) / 2);z-index:var(--vocs-zIndex_gutterRight)}.vocs_DocsLayout_gutterRight::-webkit-scrollbar{display:none}.vocs_DocsLayout_gutterRight_withSidebar{width:calc(100vw - var(--vocs-content_width) - var(--vocs_DocsLayout_leftGutterWidth))}.vocs_DocsLayout_outlinePopover{display:none;overflow-y:auto;height:calc(100vh - var(--vocs-topNav_height) - var(--vocs-topNav_curtainHeight))}.vocs_DocsLayout_sidebar{padding:var(--vocs-space_0) var(--vocs-sidebar_horizontalPadding)}.vocs_DocsLayout_sidebarDrawer{display:none}@media screen and (max-width:720px){.vocs_DocsLayout_content{overflow-x:hidden}}@media screen and (min-width:1081px){.vocs_DocsLayout_content_withTopNav{padding-top:calc(var(--vocs-topNav_height) + var(--vocs_Banner_bannerHeight, 0px))}.vocs_DocsLayout_gutterTop{padding-left:calc(var(--vocs_DocsLayout_leftGutterWidth) - var(--vocs-sidebar_width));padding-right:calc(var(--vocs_DocsLayout_leftGutterWidth) - var(--vocs-sidebar_width));position:fixed;top:var(--vocs_Banner_bannerHeight, 0px)}.vocs_DocsLayout_gutterTop_offsetLeftGutter{padding-left:var(--vocs_DocsLayout_leftGutterWidth)}.vocs_DocsLayout_gutterTopCurtain{position:fixed;top:calc(var(--vocs-topNav_height) + var(--vocs_Banner_bannerHeight, 0px))}.vocs_DocsLayout_gutterTopCurtain_withSidebar{margin-left:var(--vocs_DocsLayout_leftGutterWidth)}}@media screen and (max-width:1080px){.vocs_DocsLayout_content{margin-left:auto;margin-right:auto}.vocs_DocsLayout_gutterLeft{display:none}.vocs_DocsLayout_gutterTop{position:initial}.vocs_DocsLayout_gutterTop_sticky,.vocs_DocsLayout_gutterTopCurtain{position:sticky;top:0}.vocs_DocsLayout_outlinePopover,.vocs_DocsLayout_sidebarDrawer{display:block}}@media screen and (max-width:1280px){.vocs_DocsLayout_gutterRight{display:none}}@layer vocs_reset;html,body,.vocs_DocsLayout{font-family:var(--vocs-fontFamily_default);font-feature-settings:"rlig" 1,"calt" 1;font-size:var(--vocs-fontSize_root)}@layer vocs_reset{*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid}*:focus-visible{outline:2px solid var(--vocs-color_borderAccent);outline-offset:2px;outline-style:dashed}html,body{-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;line-height:inherit;margin:0;padding:0;border:0;text-rendering:optimizeLegibility}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit;text-wrap:balance}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--vocs-fontFamily_mono);font-size:var(--vocs-fontSize_root)}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-color:inherit;border-collapse:collapse;text-indent:0}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none;-webkit-appearance:button;-moz-appearance:button;appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{outline:auto}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none;appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1}input::placeholder,textarea::placeholder{opacity:1}button,[role=button]{cursor:pointer}:disabled{overflow:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}}.vocs_Header{border-bottom:1px solid var(--vocs-color_border)}.vocs_Header:not(:last-child){margin-bottom:var(--vocs-space_28);padding-bottom:var(--vocs-space_28)}[data-layout=landing] .vocs_Header{padding-bottom:var(--vocs-space_16)}[data-layout=landing] .vocs_Header:not(:first-child){padding-top:var(--vocs-space_36)}.vocs_H2{font-size:var(--vocs-fontSize_h2);letter-spacing:-.02em}.vocs_H2.vocs_H2:not(:last-child){margin-bottom:var(--vocs-space_24)}:not(.vocs_Header)+.vocs_H2:not(:only-child){border-top:1px solid var(--vocs-color_border);margin-top:var(--vocs-space_56);padding-top:var(--vocs-space_24)}[data-layout=landing] .vocs_H2.vocs_H2{border-top:none;margin-top:var(--vocs-space_24);padding-top:0}.vocs_H3{font-size:var(--vocs-fontSize_h3)}.vocs_H3:not(:first-child){margin-top:var(--vocs-space_18);padding-top:var(--vocs-space_18)}.vocs_H3.vocs_H3:not(:last-child){margin-bottom:var(--vocs-space_24)}.vocs_H2+.vocs_H3{padding-top:var(--vocs-space_0)}.vocs_H4{font-size:var(--vocs-fontSize_h4)}.vocs_H4:not(:first-child){margin-top:var(--vocs-space_18);padding-top:var(--vocs-space_12)}.vocs_H4.vocs_H4:not(:last-child){margin-bottom:var(--vocs-space_24)}.vocs_H3+.vocs_H4{padding-top:var(--vocs-space_0)}.vocs_H5{font-size:var(--vocs-fontSize_h5)}.vocs_H5:not(:first-child){margin-top:var(--vocs-space_16)}.vocs_H5.vocs_H5:not(:last-child){margin-bottom:var(--vocs-space_24)}.vocs_H4+.vocs_H5{padding-top:var(--vocs-space_0)}.vocs_H6{font-size:var(--vocs-fontSize_h6)}.vocs_H6:not(:first-child){margin-top:var(--vocs-space_16)}.vocs_H6.vocs_H6:not(:last-child){margin-bottom:var(--vocs-space_24)}.vocs_H5+.vocs_H6{padding-top:var(--vocs-space_0)}.vocs_Tabs{background-color:var(--vocs-color_codeBlockBackground);border:1px solid var(--vocs-color_codeInlineBorder);border-radius:var(--vocs-borderRadius_4)}.vocs_Tabs_list{background-color:var(--vocs-color_codeTitleBackground);border-bottom:1px solid var(--vocs-color_border);border-top-left-radius:var(--vocs-borderRadius_4);border-top-right-radius:var(--vocs-borderRadius_4);display:flex;padding:var(--vocs-space_0) var(--vocs-space_14)}.vocs_Tabs_trigger{border-bottom:2px solid transparent;color:var(--vocs-color_text3);font-size:var(--vocs-fontSize_14);font-weight:var(--vocs-fontWeight_medium);padding:var(--vocs-space_8) var(--vocs-space_8) var(--vocs-space_6) var(--vocs-space_8);transition:color .1s}.vocs_Tabs_trigger:hover{color:var(--vocs-color_text)}.vocs_Tabs_trigger[data-state=active]{border-bottom:2px solid var(--vocs-color_borderAccent);color:var(--vocs-color_title)}.vocs_Tabs_content{background-color:var(--vocs-color_codeBlockBackground)}.vocs_Tabs_content:not([data-shiki=true]){padding:var(--vocs-space_20) var(--vocs-space_22)}.vocs_Tabs pre{margin-bottom:var(--vocs-space_0)}@media screen and (max-width:720px){.vocs_Tabs_list{border-radius:0;padding:var(--vocs-space_0) var(--vocs-space_8)}.vocs_Tabs_content:not([data-shiki=true]){padding:var(--vocs-space_20) var(--vocs-space_16)}.vocs_Tabs pre{margin:unset}}.vocs_Step:not(:last-child){margin-bottom:var(--vocs-space_24)}.vocs_Step_title{margin-bottom:var(--vocs-space_8);position:relative}.vocs_Step_title:before{content:counter(step);align-items:center;background-color:var(--vocs-color_background4);border-radius:100%;border:.5em solid var(--vocs-color_background);box-sizing:content-box;color:var(--vocs-color_text2);counter-increment:step;display:flex;font-size:.625em;font-weight:var(--vocs-fontWeight_regular);height:2em;justify-content:center;left:calc(-25.125px - 1.45em);position:absolute;top:-.25em;width:2em}.vocs_H2+.vocs_Step_content,.vocs_H3+.vocs_Step_content,.vocs_H4+.vocs_Step_content,.vocs_H5+.vocs_Step_content,.vocs_H6+.vocs_Step_content{margin-top:calc(var(--vocs-space_8) * -1)}.vocs_Step_content>*:not(:last-child){margin-bottom:var(--vocs-space_16)}.vocs_Step_content>*:last-child{margin-bottom:var(--vocs-space_0)}@media screen and (max-width:720px){.vocs_Step_content>.vocs_Tabs,.vocs_Step_content>.vocs_CodeBlock{outline:6px solid var(--vocs-color_background);margin-left:calc(-1 * var(--vocs-space_44) - 2px);margin-right:calc(-1 * var(--vocs-space_16))}.vocs_Step_content .vocs_Tabs pre.shiki{border-top:none}}.vocs_Callout{border-radius:var(--vocs-borderRadius_4);display:flex;gap:var(--vocs-space_8);font-size:var(--vocs-fontSize_14);padding:var(--vocs-space_12) var(--vocs-space_12);margin-bottom:var(--vocs-space_16)}.vocs_Callout_content{width:100%}.vocs_Callout_icon{height:1em;margin-top:.4em;width:1em}.vocs_Callout_note{background-color:var(--vocs-color_noteBackground);border:1px solid var(--vocs-color_noteBorder);color:var(--vocs-color_noteText)}.vocs_Callout_info{background-color:var(--vocs-color_infoBackground);border:1px solid var(--vocs-color_infoBorder);color:var(--vocs-color_infoText)}.vocs_Callout_warning{background-color:var(--vocs-color_warningBackground);border:1px solid var(--vocs-color_warningBorder);color:var(--vocs-color_warningText)}.vocs_Callout_danger{background-color:var(--vocs-color_dangerBackground);border:1px solid var(--vocs-color_dangerBorder);color:var(--vocs-color_dangerText)}.vocs_Callout_tip{background-color:var(--vocs-color_tipBackground);border:1px solid var(--vocs-color_tipBorder);color:var(--vocs-color_tipText)}.vocs_Callout_success{background-color:var(--vocs-color_successBackground);border:1px solid var(--vocs-color_successBorder);color:var(--vocs-color_successText)}@media screen and (max-width:720px){:not(.vocs_Step_content)>.vocs_Callout{border-radius:0;border-left-width:0;border-right-width:0;margin-left:calc(-1 * var(--vocs-space_16));margin-right:calc(-1 * var(--vocs-space_16))}}.vocs_Content{background-color:var(--vocs-color_background);flex:1;max-width:var(--vocs-content_width);padding:var(--vocs-content_verticalPadding) var(--vocs-content_horizontalPadding);position:relative;width:100%}.vocs_Callout_content>*+.vocs_Details{margin-top:-8px}@layer vocs_global;:root.dark{color-scheme:dark}:root.dark pre.shiki span:not(.line),:root.dark :not(pre.shiki) .line span{color:var(--shiki-dark)!important}pre.shiki{background-color:var(--vocs-color_codeBlockBackground)!important}.vocs_Content>*:not(:last-child),.vocs_Details>*:not(:last-child){margin-bottom:var(--vocs-space_24)}.vocs_Callout_content>*:not(:last-child),.vocs_Callout_content>.vocs_Details>*:not(:last-child){margin-bottom:var(--vocs-space_16)}.vocs_Content>*:last-child,.vocs_Callout_content>*:last-child,.vocs_Details>*:last-child{margin-bottom:var(--vocs-space_0)}#app[aria-hidden=true]{background:var(--vocs-color_background)}@layer vocs_global{:root{background-color:var(--vocs-color_background);color:var(--vocs-color_text);line-height:var(--vocs-lineHeight_paragraph);font-size:var(--vocs-fontSize_root);font-weight:var(--vocs-fontWeight_regular)}}@media screen and (max-width:720px){:root{background-color:var(--vocs-color_backgroundDark)}}:root{--vocs-twoslash_borderColor: var(--vocs-color_border2);--vocs-twoslash_underlineColor: currentColor;--vocs-twoslash_popupBackground: var(--vocs-color_background);--vocs-twoslash_popupShadow: rgba(0, 0, 0, .08) 0px 1px 4px;--vocs-twoslash_matchedColor: inherit;--vocs-twoslash_unmatchedColor: #888;--vocs-twoslash_cursorColor: #8888;--vocs-twoslash_errorColor: var(--vocs-color_textRed);--vocs-twoslash_errorBackground: var(--vocs-color_backgroundRedTint2);--vocs-twoslash_highlightedBackground: var(--vocs-color_background);--vocs-twoslash_highlightedBorder: var(--vocs-color_background);--vocs-twoslash_tagColor: var(--vocs-color_textBlue);--vocs-twoslash_tagBackground: var(--vocs-color_backgroundBlueTint);--vocs-twoslash_tagWarnColor: var(--vocs-color_textYellow);--vocs-twoslash_tagWarnBackground: var(--vocs-color_backgroundYellowTint);--vocs-twoslash_tagAnnotateColor: var(--vocs-color_textGreen);--vocs-twoslash_tagAnnotateBackground: var(--vocs-color_backgroundGreenTint2)}:root.dark{--vocs-twoslash_borderColor: var(--vocs-color_border);--vocs-twoslash_underlineColor: currentColor;--vocs-twoslash_popupBackground: var(--vocs-color_background);--vocs-twoslash_popupShadow: rgba(0, 0, 0, .08) 0px 1px 4px;--vocs-twoslash_matchedColor: inherit;--vocs-twoslash_unmatchedColor: #888;--vocs-twoslash_cursorColor: #8888;--vocs-twoslash_errorColor: var(--vocs-color_textRed);--vocs-twoslash_errorBackground: var(--vocs-color_backgroundRedTint2);--vocs-twoslash_highlightedBackground: var(--vocs-color_background);--vocs-twoslash_highlightedBorder: var(--vocs-color_background);--vocs-twoslash_tagColor: var(--vocs-color_textBlue);--vocs-twoslash_tagBackground: var(--vocs-color_backgroundBlueTint);--vocs-twoslash_tagWarnColor: var(--vocs-color_textYellow);--vocs-twoslash_tagWarnBackground: var(--vocs-color_backgroundYellowTint);--vocs-twoslash_tagAnnotateColor: var(--vocs-color_textGreen);--vocs-twoslash_tagAnnotateBackground: var(--vocs-color_backgroundGreenTint2)}:root .twoslash-popup-info-hover,:root .twoslash-popup-info{--shiki-light-bg: var(--vocs-color_background2)}:root .twoslash-popup-info{width:-moz-max-content;width:max-content}:root.dark .twoslash-popup-info,:root.dark .twoslash-popup-info-hover{--shiki-dark-bg: var(--vocs-color_background5)}.twoslash-query-persisted>.twoslash-popup-info{z-index:1}:not(.twoslash-query-persisted)>.twoslash-popup-info{z-index:2}.twoslash:hover .twoslash-hover{border-color:var(--vocs-twoslash_underlineColor)}.twoslash .twoslash-hover{border-bottom:1px dotted transparent;transition-timing-function:ease;transition:border-color .3s}.twoslash-query-persisted{position:relative}.twoslash .twoslash-popup-info{position:absolute;top:0;left:0;opacity:0;display:inline-block;transform:translateY(1.1em);background:var(--vocs-twoslash_popupBackground);border:1px solid var(--vocs-twoslash_borderColor);transition:opacity .3s;border-radius:4px;max-width:540px;padding:4px 6px;pointer-events:none;text-align:left;z-index:20;white-space:pre-wrap;-webkit-user-select:none;-moz-user-select:none;user-select:none;box-shadow:var(--vocs-twoslash_popupShadow)}.twoslash .twoslash-popup-info-hover{background:var(--vocs-twoslash_popupBackground);border:1px solid var(--vocs-twoslash_borderColor);border-radius:4px;box-shadow:var(--vocs-twoslash_popupShadow);display:inline-block;max-width:500px;pointer-events:auto;position:fixed;opacity:1;transition:opacity .3s;white-space:pre-wrap;-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:20}.twoslash .twoslash-popup-scroll-container{max-height:300px;padding:4px 0;overflow-y:auto;-ms-overflow-style:none;scrollbar-width:none}.twoslash-popup-arrow{position:absolute;top:-4px;left:1em;border-top:1px solid var(--vocs-twoslash_borderColor);border-right:1px solid var(--vocs-twoslash_borderColor);background:var(--vocs-twoslash_popupBackground);transform:rotate(-45deg);width:6px;height:6px;pointer-events:none}.twoslash .twoslash-popup-scroll-container::-webkit-scrollbar{display:none}.twoslash .twoslash-popup-jsdoc{border-top:1px solid var(--vocs-color_border2);color:var(--vocs-color_text);font-family:sans-serif;font-weight:500;margin-top:4px;padding:4px 10px 0}.twoslash-tag-line+.twoslash-tag-line{margin-top:-.2em}.twoslash-query-persisted .twoslash-popup-info{z-index:9;transform:translateY(1.5em)}.twoslash-hover:hover .twoslash-popup-info,.twoslash-query-persisted .twoslash-popup-info{opacity:1;pointer-events:auto}.twoslash-popup-info:hover,.twoslash-popup-info-hover:hover{-webkit-user-select:auto;-moz-user-select:auto;user-select:auto}.twoslash-error-line{position:relative;background-color:var(--vocs-twoslash_errorBackground);border-left:2px solid var(--vocs-twoslash_errorColor);color:var(--vocs-twoslash_errorColor);margin:.2em 0}.twoslash-error{background:url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23c94824'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat-x bottom left;padding-bottom:2px}.twoslash-completion-cursor{position:relative}.twoslash-completion-cursor .twoslash-completion-list{-webkit-user-select:none;-moz-user-select:none;user-select:none;position:absolute;top:0;left:0;transform:translateY(1.2em);margin:3px 0 0 -1px;z-index:8;box-shadow:var(--vocs-twoslash_popupShadow);background:var(--vocs-twoslash_popupBackground);border:1px solid var(--vocs-twoslash_borderColor)}.twoslash-completion-list{border-radius:4px;font-size:.8rem;padding:4px;display:flex;flex-direction:column;gap:4px;width:240px}.twoslash-completion-list:hover{-webkit-user-select:auto;-moz-user-select:auto;user-select:auto}.twoslash-completion-list:before{content:" ";background-color:var(--vocs-twoslash_cursorColor);width:2px;position:absolute;top:-1.6em;height:1.4em;left:-1px}.twoslash-completion-list .twoslash-completion-list-item{overflow:hidden;display:flex;align-items:center;gap:.5em;line-height:1em}.twoslash-completion-list .twoslash-completion-list-item span.twoslash-completions-unmatched.twoslash-completions-unmatched.twoslash-completions-unmatched{color:var(--vocs-twoslash_unmatchedColor)!important}.twoslash-completion-list .deprecated{text-decoration:line-through;opacity:.5}.twoslash-completion-list .twoslash-completion-list-item span.twoslash-completions-matched.twoslash-completions-unmatched.twoslash-completions-unmatched{color:var(--vocs-twoslash_matchedColor)!important}.twoslash-tag-line{position:relative;background-color:var(--vocs-twoslash_tagBackground);border-left:2px solid var(--vocs-twoslash_tagColor);color:var(--vocs-twoslash_tagColor);margin:.2em 0;display:flex;align-items:center;gap:.3em}.twoslash-tag-line+.line[data-empty-line]+.twoslash-tag-line{margin-top:-1.95em}.twoslash-tag-line .twoslash-tag-icon{width:1.1em;color:inherit}.twoslash-tag-line.twoslash-tag-error-line{background-color:var(--vocs-twoslash_errorBackground);border-left:2px solid var(--vocs-twoslash_errorColor);color:var(--vocs-twoslash_errorColor)}.twoslash-tag-line.twoslash-tag-warn-line{background-color:var(--vocs-twoslash_tagWarnBackground);border-left:2px solid var(--vocs-twoslash_tagWarnColor);color:var(--vocs-twoslash_tagWarnColor)}.twoslash-tag-line.twoslash-tag-annotate-line{background-color:var(--vocs-twoslash_tagAnnotateBackground);border-left:2px solid var(--vocs-twoslash_tagAnnotateColor);color:var(--vocs-twoslash_tagAnnotateColor)}.twoslash-highlighted{border-radius:var(--vocs-borderRadius_2);background-color:var(--vocs-color_codeCharacterHighlightBackground)!important;box-shadow:0 0 0 2px var(--vocs-color_codeCharacterHighlightBackground),0 0 0 3px var(--vocs-color_codeCharacterHighlightBorder)}@media(prefers-reduced-motion:reduce){.twoslash *{transition:none!important}}.tag-line{position:relative;margin:.2em 0;display:flex;align-items:center;gap:.3em}.tag-line+.tag-line{margin-top:-.2em}.tag-line+.line[data-empty-line]+.tag-line{margin-top:-1.95em}.tag-line.tag-error-line{background-color:var(--vocs-twoslash_errorBackground);border-left:2px solid var(--vocs-twoslash_errorColor)!important;color:var(--vocs-twoslash_errorColor)}.tag-line.tag-log-line{background-color:var(--vocs-twoslash_tagBackground);border-left:2px solid var(--vocs-twoslash_tagColor)!important;color:var(--vocs-twoslash_tagColor)}.tag-line.tag-warn-line{background-color:var(--vocs-twoslash_tagWarnBackground);border-left:2px solid var(--vocs-twoslash_tagWarnColor)!important;color:var(--vocs-twoslash_tagWarnColor)}.tag-line.tag-annotate-line{background-color:var(--vocs-twoslash_tagAnnotateBackground);border-left:2px solid var(--vocs-twoslash_tagAnnotateColor)!important;color:var(--vocs-twoslash_tagAnnotateColor)}.vocs_ExternalLink:after{content:"";background-color:currentColor;color:var(--vocs_ExternalLink_arrowColor);display:inline-block;height:.5em;margin-bottom:.1em;margin-left:.325em;margin-right:.25em;width:.5em;-webkit-mask:var(--vocs_ExternalLink_iconUrl) no-repeat center / contain;mask:var(--vocs_ExternalLink_iconUrl) no-repeat center / contain}.vocs_Link_accent{color:var(--vocs-color_link);font-weight:var(--vocs-fontWeight_medium);text-underline-offset:var(--vocs-space_2);text-decoration:underline;transition:color .1s}.vocs_Link_accent:hover{color:var(--vocs-color_linkHover)}.vocs_Link_styleless{--vocs_ExternalLink_arrowColor: var(--vocs-color_text3)}.vocs_H1{font-size:var(--vocs-fontSize_h1);letter-spacing:-.02em}.vocs_Heading{align-items:center;color:var(--vocs-color_heading);font-weight:var(--vocs-fontWeight_semibold);gap:.25em;line-height:var(--vocs-lineHeight_heading);position:relative}.vocs_Heading_slugTarget{position:absolute;top:0;visibility:hidden}@media screen and (min-width:1081px){.vocs_Heading_slugTarget{top:calc(-1 * (var(--vocs-topNav_height)))}.vocs_Header .vocs_Heading_slugTarget,.vocs_Step_title .vocs_Heading_slugTarget,.vocs_Header+.vocs_Heading .vocs_Heading_slugTarget{top:calc(-1 * (var(--vocs-topNav_height) + var(--vocs-space_24)))}}@media screen and (max-width:1080px){.vocs_Heading_slugTarget{top:calc(-1 * var(--vocs-topNav_curtainHeight))}.vocs_Header .vocs_Heading_slugTarget,.vocs_Header+.vocs_Heading .vocs_Heading_slugTarget{top:calc(-1 * calc(var(--vocs-topNav_curtainHeight) + var(--vocs-space_24)))}}.vocs_Blockquote{border-left:2px solid var(--vocs-color_blockquoteBorder);padding-left:var(--vocs-space_16);margin-bottom:var(--vocs-space_16)}.vocs_H2+.vocs_List,.vocs_H3+.vocs_List,.vocs_H4+.vocs_List,.vocs_H5+.vocs_List,.vocs_H6+.vocs_List{margin-top:calc(var(--vocs-space_8) * -1)}.vocs_Paragraph+.vocs_List{margin-top:calc(-1 * var(--vocs-space_8))}.vocs_List_ordered{list-style:decimal;padding-left:var(--vocs-space_20);margin-bottom:var(--vocs-space_16)}.vocs_List_ordered .vocs_List_ordered{list-style:lower-alpha}.vocs_List_ordered .vocs_List_ordered .vocs_List_ordered{list-style:lower-roman}.vocs_List_unordered{list-style:disc;padding-left:var(--vocs-space_24);margin-bottom:var(--vocs-space_16)}.vocs_List_unordered .vocs_List_unordered{list-style:circle}.vocs_List_ordered .vocs_List_ordered,.vocs_List_unordered .vocs_List_unordered,.vocs_List_ordered .vocs_List_unordered,.vocs_List_unordered .vocs_List_ordered{margin-bottom:var(--vocs-space_0);padding-top:var(--vocs-space_8);padding-left:var(--vocs-space_16);padding-bottom:var(--vocs-space_0)}.vocs_List_unordered.contains-task-list{list-style:none;padding-left:var(--vocs-space_12)}.vocs_Paragraph{line-height:var(--vocs-lineHeight_paragraph);letter-spacing:.005em}.vocs_Blockquote>.vocs_Paragraph{color:var(--vocs-color_blockquoteText);margin-bottom:var(--vocs-space_8)}.vocs_H2+.vocs_Paragraph,.vocs_H3+.vocs_Paragraph,.vocs_H4+.vocs_Paragraph,.vocs_H5+.vocs_Paragraph,.vocs_H6+.vocs_Paragraph,.vocs_List+.vocs_Paragraph{margin-top:calc(var(--vocs-space_8) * -1)}.vocs_Paragraph+.vocs_Paragraph{margin-top:calc(-1 * var(--vocs-space_8))}.vocs_NotFound{align-items:center;display:flex;flex-direction:column;max-width:400px;margin:0 auto;padding-top:var(--vocs-space_64)}.vocs_NotFound_divider{border-color:var(--vocs-color_border);width:50%}.vocs_DesktopSearch_search{align-items:center;background-color:var(--vocs-color_background3);border:1px solid var(--vocs-color_border);border-radius:var(--vocs-borderRadius_8);color:var(--vocs-color_text3);display:flex;font-size:var(--vocs-fontSize_14);font-weight:var(--vocs-fontWeight_regular);gap:var(--vocs-space_6);height:var(--vocs-space_40);max-width:15.5rem;padding-left:var(--vocs-space_12);padding-right:var(--vocs-space_12);position:relative;width:100%;transition:color .1s,border-color .1s}.vocs_DesktopSearch_search:hover{color:var(--vocs-color_text);border-color:var(--vocs-color_border2)}.vocs_DesktopSearch_searchCommand{align-items:center;border:1.5px solid var(--vocs-color_text3);border-radius:var(--vocs-borderRadius_4);color:var(--vocs-color_text3);display:flex;height:var(--vocs-space_12);justify-content:center;margin-left:auto;margin-top:var(--vocs-space_1);padding:var(--vocs-space_1);width:var(--vocs-space_12)}:root:not(.dark) .vocs_utils_visibleDark{display:none}:root.dark .vocs_utils_visibleLight{display:none}.vocs_utils_visuallyHidden{clip:rect(0 0 0 0);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}.vocs_KeyboardShortcut{align-items:center;display:inline-flex;gap:var(--vocs-space_6);font-size:var(--vocs-fontSize_12)}.vocs_KeyboardShortcut_kbdGroup{align-items:center;display:inline-flex;gap:var(--vocs-space_3)}@media screen and (max-width:720px){.vocs_KeyboardShortcut{display:none}}.vocs_Kbd{color:var(--vocs-color_text2);display:inline-block;border-radius:var(--vocs-borderRadius_3);font-size:var(--vocs-fontSize_11);font-family:var(--vocs-fontFamily_default);font-feature-settings:cv08;line-height:105%;min-width:20px;padding:var(--vocs-space_3);padding-left:var(--vocs-space_4);padding-right:var(--vocs-space_4);padding-top:var(--vocs-space_3);text-align:center;text-transform:capitalize;vertical-align:baseline;border:.5px solid var(--vocs-color_border);background-color:var(--vocs-color_background3);box-shadow:var(--vocs-color_shadow2) 0 2px 0 0}@keyframes vocs_SearchDialog_fadeIn{0%{opacity:0}to{opacity:1}}@keyframes vocs_SearchDialog_fadeAndSlideIn{0%{opacity:0;transform:translate(-50%,-5%) scale(.96)}to{opacity:1;transform:translate(-50%) scale(1)}}.vocs_SearchDialog{animation:vocs_SearchDialog_fadeAndSlideIn .1s ease-in-out;background:var(--vocs-color_background);border-radius:var(--vocs-borderRadius_6);display:flex;flex-direction:column;gap:var(--vocs-space_8);height:-moz-min-content;height:min-content;left:50%;margin:64px auto;max-height:min(100vh - 128px,900px);padding:var(--vocs-space_12);padding-bottom:var(--vocs-space_8);position:fixed;top:0;transform:translate(-50%);width:min(100vw - 60px,775px);z-index:var(--vocs-zIndex_backdrop)}.vocs_SearchDialog_overlay{animation:vocs_SearchDialog_fadeIn .1s ease-in-out;background:#0009;position:fixed;inset:0;z-index:var(--vocs-zIndex_backdrop)}.vocs_SearchDialog_searchBox{align-items:center;border:1px solid var(--vocs-color_border);border-radius:var(--vocs-borderRadius_4);display:flex;gap:var(--vocs-space_8);padding-left:var(--vocs-space_8);padding-right:var(--vocs-space_8);margin-bottom:var(--vocs-space_8);width:100%}.vocs_SearchDialog_searchBox:focus-within{border-color:var(--vocs-color_borderAccent)}.vocs_SearchDialog_searchInput{background:transparent;display:flex;font-size:var(--vocs-fontSize_16);height:var(--vocs-space_40);width:100%}.vocs_SearchDialog_searchInput:focus{outline:none}.vocs_SearchDialog_searchInput::-moz-placeholder{color:var(--vocs-color_text4)}.vocs_SearchDialog_searchInput::placeholder{color:var(--vocs-color_text4)}.vocs_SearchDialog_searchInputIcon{color:var(--vocs-color_text3)}.vocs_SearchDialog_searchInputIconMobile{display:none}.vocs_SearchDialog_results{display:flex;flex-direction:column;gap:var(--vocs-space_8);overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;width:100%}.vocs_SearchDialog_result{border:1.5px solid var(--vocs-color_border);border-radius:var(--vocs-borderRadius_4);width:100%}.vocs_SearchDialog_result:focus-within{border-color:var(--vocs-color_borderAccent)}.vocs_SearchDialog_result>a{display:flex;flex-direction:column;gap:var(--vocs-space_8);min-height:var(--vocs-space_36);outline:none;justify-content:center;padding:var(--vocs-space_12);width:100%}.vocs_SearchDialog_resultSelected{border-color:var(--vocs-color_borderAccent)}.vocs_SearchDialog_resultIcon{color:var(--vocs-color_textAccent);margin-right:1px;width:15px}.vocs_SearchDialog_titles{align-items:center;display:flex;flex-wrap:wrap;font-weight:var(--vocs-fontWeight_medium);gap:var(--vocs-space_4);line-height:22px}.vocs_SearchDialog_title{align-items:center;display:flex;gap:var(--vocs-space_4);white-space:nowrap}.vocs_SearchDialog_titleIcon{color:var(--vocs-color_text);display:inline-block;opacity:.5}.vocs_SearchDialog_resultSelected .vocs_SearchDialog_title,.vocs_SearchDialog_resultSelected .vocs_SearchDialog_titleIcon{color:var(--vocs-color_textAccent)}.vocs_SearchDialog_content{padding:0}.vocs_SearchDialog_excerpt{max-height:8.75rem;overflow:hidden;opacity:.5;position:relative}.vocs_SearchDialog_excerpt:before{content:"";position:absolute;top:-1px;left:0;width:100%;height:8px;background:linear-gradient(var(--vocs-color_background),transparent);z-index:1000}.vocs_SearchDialog_excerpt:after{content:"";position:absolute;bottom:-1px;left:0;width:100%;height:12px;background:linear-gradient(transparent,var(--vocs-color_background));z-index:1000}.vocs_SearchDialog_title mark,.vocs_SearchDialog_excerpt mark{background-color:var(--vocs-color_searchHighlightBackground);color:var(--vocs-color_searchHighlightText);border-radius:var(--vocs-borderRadius_2);padding-bottom:0;padding-left:var(--vocs-space_2);padding-right:var(--vocs-space_2);padding-top:0}.vocs_SearchDialog_resultSelected .vocs_SearchDialog_excerpt{opacity:1}.vocs_SearchDialog_searchShortcuts{align-items:center;color:var(--vocs-color_text2);display:flex;gap:var(--vocs-space_20);font-size:var(--vocs-fontSize_14)}.vocs_SearchDialog_searchShortcutsGroup{align-items:center;display:inline-flex;gap:var(--vocs-space_3);margin-right:var(--vocs-space_6)}@media screen and (max-width:720px){.vocs_SearchDialog{border-radius:0;height:calc(100vh - env(safe-area-inset-top) - env(safe-area-inset-bottom));margin:0;max-height:unset;width:100vw}.vocs_SearchDialog_searchInputIconDesktop{display:none}.vocs_SearchDialog_searchInputIconMobile{display:block}.vocs_SearchDialog_excerpt{opacity:1}.vocs_SearchDialog_searchShortcuts{display:none}}.vocs_DesktopTopNav{align-items:center;display:flex;gap:var(--vocs-space_8);justify-content:space-between;padding:0 var(--vocs-topNav_horizontalPadding);height:var(--vocs-topNav_height)}.vocs_DesktopTopNav_withLogo{padding-left:calc(((100% - var(--vocs-content_width)) / 2) + var(--vocs-topNav_horizontalPadding))}.vocs_DesktopTopNav_button{border-radius:var(--vocs-borderRadius_4);padding:var(--vocs-space_8)}.vocs_DesktopTopNav_content{right:calc(-1 * var(--vocs-space_24))}.vocs_DesktopTopNav_curtain{background:linear-gradient(var(--vocs-color_background),transparent 70%);height:30px;opacity:.98;width:100%}.vocs_DesktopTopNav_divider{background-color:var(--vocs-color_border);height:35%;width:1px}.vocs_DesktopTopNav_group{align-items:center;display:flex}.vocs_DesktopTopNav_icon{color:var(--vocs-color_text2);transition:color .1s}.vocs_DesktopTopNav_button:hover .vocs_DesktopTopNav_icon{color:var(--vocs-color_textHover)}.vocs_DesktopTopNav_item{align-items:center;display:flex;height:100%;position:relative;white-space:nowrap}.vocs_DesktopTopNav_logo{padding-left:var(--vocs-sidebar_horizontalPadding);padding-right:var(--vocs-sidebar_horizontalPadding);width:var(--vocs-sidebar_width)}.vocs_DesktopTopNav_logoWrapper{display:flex;height:100%;justify-content:flex-end;left:0;position:absolute;width:var(--vocs_DocsLayout_leftGutterWidth)}.vocs_DesktopTopNav_section{align-items:center;display:flex;height:100%;gap:var(--vocs-space_24)}@media screen and (max-width:1080px){.vocs_DesktopTopNav,.vocs_DesktopTopNav_curtain{display:none}}@media screen and (max-width:1280px){.vocs_DesktopTopNav_hideCompact{display:none}}@keyframes vocs_NavigationMenu_fadeIn{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}.vocs_NavigationMenu_list{display:flex;gap:var(--vocs-space_20)}.vocs_NavigationMenu_link{align-items:center;display:flex;color:var(--vocs-color_text);font-size:var(--vocs-fontSize_14);font-weight:var(--vocs-fontWeight_medium);height:100%}.vocs_NavigationMenu_link:hover{color:var(--vocs-color_textHover)}.vocs_NavigationMenu_link[data-active=true]{color:var(--vocs-color_textAccent)}.vocs_NavigationMenu_trigger:after{content:"";background-color:currentColor;color:var(--vocs-color_text3);display:inline-block;height:.625em;margin-left:.325em;width:.625em;-webkit-mask:var(--vocs_NavigationMenu_chevronDownIcon) no-repeat center / contain;mask:var(--vocs_NavigationMenu_chevronDownIcon) no-repeat center / contain}.vocs_NavigationMenu_content{background-color:var(--vocs-color_background);border:1px solid var(--vocs-color_border);border-radius:var(--vocs-borderRadius_4);box-shadow:0 3px 10px var(--vocs-color_shadow);display:flex;flex-direction:column;padding:var(--vocs-space_12) var(--vocs-space_16);position:absolute;top:calc(100% + var(--vocs-space_8));min-width:200px;z-index:var(--vocs-zIndex_popover);animation:vocs_NavigationMenu_fadeIn .5s cubic-bezier(.16,1,.3,1)}:root:not(.dark) .vocs_Logo_logoDark{display:none}:root.dark .vocs_Logo_logoLight{display:none}.vocs_NavLogo_logoImage{height:50%;width:auto}.vocs_NavLogo_title{font-size:var(--vocs-fontSize_18);font-weight:var(--vocs-fontWeight_semibold);line-height:var(--vocs-lineHeight_heading)}.vocs_Footer{--vocs_Footer_iconWidth: 24px;display:flex;flex-direction:column;gap:var(--vocs-space_32);max-width:var(--vocs-content_width);overflow-x:hidden;padding:var(--vocs-space_28) var(--vocs-content_horizontalPadding)}.vocs_Footer:not([data-layout=docs]){align-items:center;gap:var(--vocs-space_16)}.vocs_Footer_container{border-bottom:1px solid var(--vocs-color_border);display:flex;justify-content:space-between;padding-bottom:var(--vocs-space_16)}.vocs_Footer_editLink{align-items:center;display:flex;font-size:var(--vocs-fontSize_14);gap:var(--vocs-space_8);text-decoration:none}.vocs_Footer_lastUpdated{color:var(--vocs-color_text3);font-size:var(--vocs-fontSize_14)}.vocs_Footer_navigation{display:flex;justify-content:space-between}.vocs_Footer_navigationIcon{width:var(--vocs_Footer_iconWidth)}.vocs_Footer_navigationIcon_left{display:flex}.vocs_Footer_navigationIcon_right{display:flex;justify-content:flex-end}.vocs_Footer_navigationItem{display:flex;flex-direction:column;gap:var(--vocs-space_4)}.vocs_Footer_navigationItem_right{align-items:flex-end}.vocs_Footer_navigationText{align-items:center;color:var(--vocs-color_heading);display:flex;font-size:var(--vocs-fontSize_18);font-weight:var(--vocs-fontWeight_medium)}.vocs_Footer_navigationTextInner{overflow:hidden;text-overflow:ellipsis;width:26ch;white-space:pre}@media screen and (max-width:720px){.vocs_Footer_navigationIcon_left,.vocs_Footer_navigationIcon_right{justify-content:center}.vocs_Footer_navigationText{font-size:var(--vocs-fontSize_12)}}@media screen and (max-width:480px){.vocs_Footer_navigationTextInner{width:20ch}}.vocs_Icon{align-items:center;display:flex;height:var(--vocs_Icon_size);width:var(--vocs_Icon_size)}.vocs_Socials{display:flex;flex-direction:row;gap:var(--vocs-space_8)}.vocs_Socials_button{align-items:center;display:flex;padding:var(--vocs-space_4)}.vocs_Socials_icon{color:var(--vocs-color_text3);transition:color .1s}.vocs_Socials_button:hover .vocs_Socials_icon{color:var(--vocs-color_textHover)}.vocs_MobileSearch_searchButton{align-items:center;display:flex;color:var(--vocs-color_text);height:var(--vocs-space_28);justify-content:center;width:var(--vocs-space_28)}@keyframes vocs_MobileTopNav_fadeIn{0%{opacity:0}to{opacity:1}}.vocs_MobileTopNav{align-items:center;background-color:var(--vocs-color_backgroundDark);border-bottom:1px solid var(--vocs-color_border);display:none;height:100%;justify-content:space-between;padding:var(--vocs-space_0) var(--vocs-content_horizontalPadding);width:100%}.vocs_MobileTopNav_button{border-radius:var(--vocs-borderRadius_4);padding:var(--vocs-space_8)}.vocs_MobileTopNav_content{left:calc(-1 * var(--vocs-space_24))}.vocs_MobileTopNav_curtain{align-items:center;background-color:var(--vocs-color_backgroundDark);border-bottom:1px solid var(--vocs-color_border);display:none;justify-content:space-between;font-size:var(--vocs-fontSize_13);font-weight:var(--vocs-fontWeight_medium);height:100%;padding:var(--vocs-space_0) var(--vocs-content_horizontalPadding);width:100%}.vocs_MobileTopNav_curtainGroup{align-items:center;display:flex;gap:var(--vocs-space_12)}.vocs_MobileTopNav_divider{background-color:var(--vocs-color_border);height:35%;width:1px}.vocs_MobileTopNav_group{align-items:center;display:flex;height:100%}.vocs_MobileTopNav_icon{color:var(--vocs-color_text2);transition:color .1s}.vocs_MobileTopNav_button:hover .vocs_MobileTopNav_icon{color:var(--vocs-color_text)}.vocs_MobileTopNav_item{position:relative}.vocs_MobileTopNav_logo{align-items:center;display:flex;height:var(--vocs-topNav_height)}.vocs_MobileTopNav_logoImage{height:30%}.vocs_MobileTopNav_menuTrigger{align-items:center;display:flex;gap:var(--vocs-space_8)}.vocs_MobileTopNav_menuTitle{max-width:22ch;overflow:hidden;text-align:left;text-overflow:ellipsis;white-space:pre}.vocs_MobileTopNav_navigationContent{display:flex;flex-direction:column;margin-left:var(--vocs-space_8)}.vocs_MobileTopNav_navigationItem{align-items:center;display:flex;justify-content:flex-start;font-size:var(--vocs-fontSize_14);font-weight:var(--vocs-fontWeight_medium);width:100%}.vocs_MobileTopNav_navigationItem:hover,.vocs_MobileTopNav_navigationItem[data-active=true],.vocs_MobileTopNav_navigationItem[data-state=open]{color:var(--vocs-color_textAccent)}.vocs_MobileTopNav_trigger:after{content:"";background-color:currentColor;display:inline-block;height:.625em;margin-left:.325em;width:.625em;-webkit-mask:var(--vocs_MobileTopNav_chevronDownIcon) no-repeat center / contain;mask:var(--vocs_MobileTopNav_chevronDownIcon) no-repeat center / contain}.vocs_MobileTopNav_trigger[data-state=open]:after{-webkit-mask:var(--vocs_MobileTopNav_chevronUpIcon) no-repeat center / contain;mask:var(--vocs_MobileTopNav_chevronUpIcon) no-repeat center / contain}.vocs_MobileTopNav_outlineTrigger{animation:vocs_MobileTopNav_fadeIn .5s cubic-bezier(.16,1,.3,1);align-items:center;color:var(--vocs-color_text2);display:flex;gap:var(--vocs-space_6)}.vocs_MobileTopNav_outlineTrigger[data-state=open]{color:var(--vocs-color_textAccent)}.vocs_MobileTopNav_outlinePopover{display:none;overflow-y:scroll;padding:var(--vocs-space_16);max-height:80vh}.vocs_MobileTopNav_section{align-items:center;display:flex;height:100%;gap:var(--vocs-space_16)}.vocs_MobileTopNav_separator{background-color:var(--vocs-color_border);height:1.75em;width:1px}.vocs_MobileTopNav_sidebarPopover{display:none;overflow-y:scroll;padding:0 var(--vocs-sidebar_horizontalPadding);max-height:80vh;width:var(--vocs-sidebar_width)}.vocs_MobileTopNav_title{font-size:var(--vocs-fontSize_18);font-weight:var(--vocs-fontWeight_semibold);line-height:var(--vocs-lineHeight_heading)}.vocs_MobileTopNav_topNavPopover{display:none;overflow-y:scroll;padding:var(--vocs-sidebar_verticalPadding) var(--vocs-sidebar_horizontalPadding);max-height:80vh;width:var(--vocs-sidebar_width)}.vocs_MobileTopNav_topNavPopoverFooter{display:flex;gap:var(--vocs-space_16);justify-content:space-between;margin-top:var(--vocs-space_8)}@media screen and (max-width:1080px){.vocs_MobileTopNav,.vocs_MobileTopNav_curtain{display:flex}.vocs_MobileTopNav_outlinePopover{display:block;max-width:300px}.vocs_MobileTopNav_sidebarPopover{display:block}.vocs_MobileTopNav_topNavPopover{display:flex;flex-direction:column}}@media screen and (max-width:720px){.vocs_MobileTopNav_navigation:not(.vocs_MobileTopNav_navigation_compact){display:none}}@media screen and (min-width:721px){.vocs_MobileTopNav_navigation.vocs_MobileTopNav_navigation_compact{display:none}}.vocs_Button_button{align-items:center;background:var(--vocs-color_background3);border:1px solid var(--vocs-color_border);border-radius:var(--vocs-borderRadius_round);color:var(--vocs-color_text);display:flex;font-size:var(--vocs-fontSize_14);font-weight:var(--vocs-fontWeight_medium);height:40px;padding:0 var(--vocs-space_18);transition:background .1s;white-space:pre;width:-moz-fit-content;width:fit-content}.vocs_Button_button:hover{background:var(--vocs-color_background4)}.vocs_Button_button_accent{background:var(--vocs-color_backgroundAccent);border:1px solid var(--vocs-color_borderAccent);color:var(--vocs-color_backgroundAccentText)}.vocs_Button_button_accent:hover{background:var(--vocs-color_backgroundAccentHover)}.vocs_AiCtaDropdown{display:flex}.vocs_AiCtaDropdown_button.vocs_AiCtaDropdown_button{align-items:center;background-color:var(--vocs-color_background);display:flex;gap:var(--vocs-space_6);height:32px;font-size:var(--vocs-fontSize_12)}.vocs_AiCtaDropdown_button:hover{background-color:var(--vocs-color_background2)}.vocs_AiCtaDropdown_button:focus-visible{outline:none}.vocs_AiCtaDropdown_buttonLeft.vocs_AiCtaDropdown_buttonLeft{border-top-right-radius:0;border-bottom-right-radius:0;padding:0 var(--vocs-space_8) 0 var(--vocs-space_12);width:130px}.vocs_AiCtaDropdown_buttonRight.vocs_AiCtaDropdown_buttonRight{border-top-left-radius:0;border-bottom-left-radius:0;border-left:none;padding:0 var(--vocs-space_8) 0 var(--vocs-space_6)}.vocs_AiCtaDropdown_dropdownMenuContent{background-color:var(--vocs-color_background);border-radius:var(--vocs-borderRadius_8);border:1px solid var(--vocs-color_border);padding:var(--vocs-space_4) var(--vocs-space_4);z-index:var(--vocs-zIndex_popover)}.vocs_AiCtaDropdown_dropdownMenuItem{display:flex;align-items:center;border-radius:var(--vocs-borderRadius_4);gap:var(--vocs-space_8);cursor:pointer;font-size:var(--vocs-fontSize_12);font-weight:var(--vocs-fontWeight_medium);padding:0 var(--vocs-space_8)}.vocs_AiCtaDropdown_dropdownMenuItem:hover{background-color:var(--vocs-color_background2)}.vocs_AiCtaDropdown_dropdownMenuItem:focus-visible{outline:none}@media screen and (max-width:1080px){.vocs_AiCtaDropdown{display:none}}.vocs_Outline{width:100%;display:flex;flex-direction:column;gap:var(--vocs-space_24)}.vocs_Outline_nav{display:flex;flex-direction:column;gap:var(--vocs-space_8)}.vocs_DocsLayout_gutterRight .vocs_Outline_nav{border-left:1px solid var(--vocs-color_border);padding-left:var(--vocs-space_16)}.vocs_Outline_heading{color:var(--vocs-color_title);font-size:var(--vocs-fontSize_13);font-weight:var(--vocs-fontWeight_semibold);line-height:var(--vocs-lineHeight_heading);letter-spacing:.025em}.vocs_Outline_items .vocs_Outline_items{padding-left:var(--vocs-space_12)}.vocs_Outline_item{line-height:var(--vocs-lineHeight_outlineItem);margin-bottom:var(--vocs-space_8);overflow:hidden;text-overflow:ellipsis;text-wrap:nowrap}.vocs_Outline_link{color:var(--vocs-color_text2);font-weight:var(--vocs-fontWeight_medium);font-size:var(--vocs-fontSize_13);transition:color .1s}.vocs_Outline_link[data-active=true]{color:var(--vocs-color_textAccent)}.vocs_Outline_link[data-active=true]:hover{color:var(--vocs-color_textAccentHover)}.vocs_Outline_link:hover{color:var(--vocs-color_textHover)}@media screen and (max-width:1080px){.vocs_Outline{gap:var(--vocs-space_12)}}.vocs_Popover{background-color:var(--vocs-color_background);border:1px solid var(--vocs-color_border);border-radius:var(--vocs-borderRadius_4);margin:0 var(--vocs-space_6);z-index:var(--vocs-zIndex_popover)}.vocs_Sidebar{display:flex;flex-direction:column;font-size:var(--vocs-fontSize_14);justify-content:space-between;overflow-y:auto;width:var(--vocs-sidebar_width)}.vocs_Sidebar_backLink{text-align:left}.vocs_Sidebar_divider{background-color:var(--vocs-color_border);width:100%;height:1px}.vocs_Sidebar_navigation{outline:0;padding-bottom:var(--vocs-space_32)}.vocs_Sidebar_navigation:first-child{padding-top:var(--vocs-space_16)}.vocs_Sidebar_group{display:flex;flex-direction:column}.vocs_Sidebar_logo{align-items:center;display:flex;height:var(--vocs-topNav_height);padding-top:var(--vocs-space_4)}.vocs_Sidebar_logoWrapper{background-color:var(--vocs-color_backgroundDark);position:sticky;top:0;z-index:var(--vocs-zIndex_gutterTopCurtain)}.vocs_Sidebar_section{display:flex;flex-direction:column;font-size:1em}.vocs_Sidebar_navigation>.vocs_Sidebar_group>.vocs_Sidebar_section+.vocs_Sidebar_section{border-top:1px solid var(--vocs-color_border)}.vocs_Sidebar_levelCollapsed{gap:var(--vocs-space_4);padding-bottom:var(--vocs-space_12)}.vocs_Sidebar_levelInset{border-left:1px solid var(--vocs-color_border);font-size:var(--vocs-fontSize_13);margin-top:var(--vocs-space_8);padding-left:var(--vocs-space_12)}.vocs_Sidebar_levelInset.vocs_Sidebar_levelInset.vocs_Sidebar_levelInset{font-weight:var(--vocs-fontWeight_regular);padding-top:0;padding-bottom:0}.vocs_Sidebar_footer{align-items:flex-end;bottom:0;background-color:var(--vocs-color_backgroundDark);display:flex;padding:var(--vocs-space_8) 0 var(--vocs-space_16);position:sticky}.vocs_Sidebar_footerContent{align-items:center;display:flex;justify-content:space-between;width:100%}.vocs_Sidebar_footerCurtain{background:linear-gradient(transparent,var(--vocs-color_backgroundDark) 80%);position:absolute;top:-34px;left:0;height:36px;width:100%}.vocs_Sidebar_items{display:flex;flex-direction:column;gap:.625em;padding-top:var(--vocs-space_16);padding-bottom:var(--vocs-space_16);font-weight:var(--vocs-fontWeight_regular)}.vocs_Sidebar_level .vocs_Sidebar_items{padding-top:var(--vocs-space_6)}.vocs_Sidebar_item{color:var(--vocs-color_text2);letter-spacing:.25px;line-height:var(--vocs-lineHeight_sidebarItem);width:100%;transition:color .1s}.vocs_Sidebar_item:hover{color:var(--vocs-color_textHover)}.vocs_Sidebar_item[data-active=true]{color:var(--vocs-color_textAccent);font-weight:var(--vocs-fontWeight_medium)}.vocs_Sidebar_disabledItem{color:var(--vocs-color_text4);pointer-events:none}.vocs_Sidebar_sectionHeader{align-items:center;display:flex;justify-content:space-between}.vocs_Sidebar_level>.vocs_Sidebar_sectionHeader{padding-top:var(--vocs-space_12)}.vocs_Sidebar_sectionHeaderActive{color:var(--vocs-color_text)}.vocs_Sidebar_sectionTitle{color:var(--vocs-color_title);font-size:var(--vocs-fontSize_14);font-weight:var(--vocs-fontWeight_medium);letter-spacing:.25px;width:100%}.vocs_Sidebar_sectionTitleLink:hover{color:var(--vocs-color_text)}.vocs_Sidebar_sectionTitleLink[data-active=true]{color:var(--vocs-color_textAccent)}.vocs_Sidebar_sectionCollapse{color:var(--vocs-color_text3);transform:rotate(90deg);transition:transform .25s}.vocs_Sidebar_sectionCollapseActive{transform:rotate(0)}@media screen and (max-width:1080px){.vocs_Sidebar{width:100%}.vocs_Sidebar_logoWrapper{display:none}.vocs_Sidebar_footer{background-color:var(--vocs-color_background)}.vocs_Sidebar_footerCurtain{display:none}}@media screen and (max-width:720px){.vocs_Sidebar_navigation{padding-bottom:0}}.vocs_ThemeToggle{border:1px solid var(--vocs-color_border);border-radius:var(--vocs-borderRadius_round);display:flex;gap:var(--vocs-space_8);padding:var(--vocs-space_4)}.vocs_ThemeToggle_themeToggleButton{color:var(--vocs-color_text4)}.vocs_ThemeToggle_themeToggleButton:hover,.vocs_ThemeToggle_themeToggleButton[data-active=true]{color:var(--vocs-color_textHover)}.vocs_SkipLink{background:var(--vocs-color_background);border-radius:var(--vocs-borderRadius_4);color:var(--vocs-color_link);font-size:var(--vocs-fontSize_14);font-weight:var(--vocs-fontWeight_semibold);left:var(--vocs-space_8);padding:var(--vocs-space_8) var(--vocs-space_16);position:fixed;text-decoration:none;top:var(--vocs-space_8);z-index:999}.vocs_SkipLink:focus{clip:auto;clip-path:none;height:auto;width:auto}:root{--vocs-color_backgroundAccent: #FFB757}:root.dark{--vocs-color_backgroundAccent: #FFB757}:root{--vocs-color_backgroundAccentHover: #f1ab4b}:root.dark{--vocs-color_backgroundAccentHover: #f1ab4b}:root{--vocs-color_backgroundAccentText: black}:root.dark{--vocs-color_backgroundAccentText: black}:root{--vocs-color_borderAccent: #f1ab4b}:root.dark{--vocs-color_borderAccent: #ffd06f}:root{--vocs-color_textAccent: #FFB757}:root.dark{--vocs-color_textAccent: #FFB757}:root{--vocs-color_textAccentHover: #e39f3f}:root.dark{--vocs-color_textAccentHover: #e39f3f}@layer properties{@supports ((-webkit-hyphens:none) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::-moz-placeholder{opacity:1}::placeholder{opacity:1}@supports (not (-webkit-appearance:-apple-pay-button)) or (contain-intrinsic-size:1px){::-moz-placeholder{color:currentColor}::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::-moz-placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.absolute{position:absolute}.relative{position:relative}.static{position:static}.block{display:block}.contents{display:contents}.hidden{display:none}.inline{display:inline}.shrink{flex-shrink:1}.resize{resize:both}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}}@font-face{font-family:CommitMono;src:url(/CommitMono-400-Regular.otf)format("opentype");font-weight:400;font-style:normal}@font-face{font-family:CommitMono;src:url(/CommitMono-700-Regular.otf)format("opentype");font-weight:700;font-style:normal}.vocs_HomePage_logo{width:100%!important;height:auto!important}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}.vocs_Section{border-top:1px solid var(--vocs-color_border);margin-top:var(--vocs-space_56);padding-top:var(--vocs-space_24)}.vocs_Anchor{color:var(--vocs-color_link);font-weight:var(--vocs-fontWeight_medium);text-underline-offset:var(--vocs-space_2);text-decoration:underline;transition:color .1s}.vocs_Callout_danger .vocs_Anchor{color:var(--vocs-color_dangerText)}.vocs_Callout_danger .vocs_Anchor:hover{color:var(--vocs-color_dangerTextHover)}.vocs_Callout_info .vocs_Anchor{color:var(--vocs-color_infoText)}.vocs_Callout_info .vocs_Anchor:hover{color:var(--vocs-color_infoTextHover)}.vocs_Callout_success .vocs_Anchor{color:var(--vocs-color_successText)}.vocs_Callout_success .vocs_Anchor:hover{color:var(--vocs-color_successTextHover)}.vocs_Callout_tip .vocs_Anchor{color:var(--vocs-color_tipText)}.vocs_Callout_tip .vocs_Anchor:hover{color:var(--vocs-color_tipTextHover)}.vocs_Callout_warning .vocs_Anchor{color:var(--vocs-color_warningText)}.vocs_Callout_warning .vocs_Anchor:hover{color:var(--vocs-color_warningTextHover)}.vocs_Anchor:hover{color:var(--vocs-color_linkHover)}.vocs_Section a.data-footnote-backref{color:var(--vocs-color_link);font-weight:var(--vocs-fontWeight_medium);text-underline-offset:var(--vocs-space_2);text-decoration:underline}.vocs_Section a.data-footnote-backref:hover{color:var(--vocs-color_linkHover)}.vocs_Autolink{opacity:0;margin-top:.1em;position:absolute;transition:opacity .1s,transform .1s;transform:translate(-2px) scale(.98)}.vocs_Heading:hover .vocs_Autolink{opacity:1;transform:translate(0) scale(1)}.vocs_Pre_wrapper{position:relative}.vocs_Code{transition:color .1s}:not(.vocs_Pre)>.vocs_Code{background-color:var(--vocs-color_codeInlineBackground);border:1px solid var(--vocs-color_codeInlineBorder);border-radius:var(--vocs-borderRadius_4);color:var(--vocs-color_codeInlineText);font-size:var(--vocs-fontSize_code);padding:var(--vocs-space_3) var(--vocs-space_6)}.vocs_Anchor>.vocs_Code{color:var(--vocs-color_link)}.vocs_Anchor:hover>.vocs_Code{color:var(--vocs-color_linkHover)}.vocs_Callout_danger .vocs_Code{color:var(--vocs-color_dangerText)}.vocs_Callout_info .vocs_Code{color:var(--vocs-color_infoText)}.vocs_Callout_success .vocs_Code{color:var(--vocs-color_successText)}.vocs_Callout_tip .vocs_Code{color:var(--vocs-color_tipText)}.vocs_Callout_warning .vocs_Code{color:var(--vocs-color_warningText)}.vocs_Heading .vocs_Code{color:inherit}.twoslash-popup-info-hover>.vocs_Code{background-color:inherit;padding:0;text-wrap:wrap}.twoslash-popup-jsdoc .vocs_Code{display:inline}.vocs_Authors{color:var(--vocs-color_text3);font-size:var(--vocs-fontSize_14)}.vocs_Authors_authors{color:var(--vocs-color_text)}.vocs_Authors_link{text-decoration:underline;text-underline-offset:2px}.vocs_Authors_link:hover{color:var(--vocs-color_text2)}.vocs_Authors_separator{color:var(--vocs-color_text3)}.vocs_BlogPosts{display:flex;flex-direction:column;gap:var(--vocs-space_32)}.vocs_BlogPosts_description{margin-top:var(--vocs-space_16)}.vocs_BlogPosts_divider{border-color:var(--vocs-color_background4)}.vocs_BlogPosts_post:hover .vocs_BlogPosts_readMore{color:var(--vocs-color_textAccent)}.vocs_BlogPosts_title{color:var(--vocs-color_heading);font-size:var(--vocs-fontSize_h2);font-weight:var(--vocs-fontWeight_semibold)}.vocs_Sponsors{border-radius:var(--vocs-borderRadius_8);display:flex;flex-direction:column;gap:var(--vocs-space_4);overflow:hidden}.vocs_Sponsors_title{background-color:var(--vocs-color_background3);border:1px solid var(--vocs-color_border);color:var(--vocs-color_text3);font-size:var(--vocs-fontSize_13);font-weight:var(--vocs-fontWeight_medium);padding:var(--vocs-space_4) 0;text-align:center}.vocs_Sponsors_row{display:flex;flex-direction:row;gap:var(--vocs-space_4)}.vocs_Sponsors_column{align-items:center;background-color:var(--vocs-color_background3);border:1px solid var(--vocs-color_border);display:flex;justify-content:center;padding-bottom:var(--vocs-space_18);padding-top:var(--vocs-space_18);width:calc(var(--vocs_Sponsors_columns) * 100%)}.vocs_Sponsors_sponsor{transition:background-color .1s}.vocs_Sponsors_sponsor:hover{background-color:var(--vocs-color_background4)}.vocs_Sponsors_image{filter:grayscale(1);height:calc(var(--vocs_Sponsors_height) * 1.2);width:75%;transition:filter .1s}.dark .vocs_Sponsors_image{filter:grayscale(1) invert(1)}@media screen and (max-width:768px){.vocs_Sponsors_column{padding-bottom:var(--vocs-space_8);padding-top:var(--vocs-space_8)}}@media screen and (min-width:768px){.vocs_Sponsors_image{padding:var(--vocs-space_8)}}.vocs_AutolinkIcon{background-color:var(--vocs-color_textAccent);display:inline-block;margin-left:.25em;height:.8em;width:.8em;-webkit-mask:var(--vocs_AutolinkIcon_iconUrl) no-repeat center / contain;mask:var(--vocs_AutolinkIcon_iconUrl) no-repeat center / contain;transition:background-color .1s}.vocs_Autolink:hover .vocs_AutolinkIcon{background-color:var(--vocs-color_textAccentHover)}@media screen and (max-width:720px){.vocs_CodeGroup{border-radius:0;border-right:none;border-left:none;margin-left:calc(-1 * var(--vocs-space_16));margin-right:calc(-1 * var(--vocs-space_16))}}.vocs_Steps{border-left:1.5px solid var(--vocs-color_border);counter-reset:step;padding-left:var(--vocs-space_24);margin-left:var(--vocs-space_12);margin-top:var(--vocs-space_24)}@media screen and (max-width:720px){.vocs_Steps{margin-left:var(--vocs-space_4)}}.vocs_Subtitle{color:var(--vocs-color_text2);font-size:var(--vocs-fontSize_subtitle);font-weight:var(--vocs-fontWeight_regular);line-height:var(--vocs-lineHeight_heading);margin-top:var(--vocs-space_4);text-wrap:balance}.vocs_HorizontalRule{border-top:1px solid var(--vocs-color_hr);margin-bottom:var(--vocs-space_16)}.vocs_ListItem{line-height:var(--vocs-lineHeight_listItem)}.vocs_ListItem:not(:last-child){margin-bottom:.5em}.vocs_CopyButton{align-items:center;background-color:color-mix(in srgb,var(--vocs-color_background2) 75%,transparent);-webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px);border:1px solid var(--vocs-color_border);border-radius:var(--vocs-borderRadius_4);color:var(--vocs-color_text3);display:flex;justify-content:center;position:absolute;right:var(--vocs-space_18);top:var(--vocs-space_18);opacity:0;height:32px;width:32px;transition:background-color .15s,opacity .15s;z-index:var(--vocs-zIndex_surface)}.vocs_CopyButton:hover{background-color:var(--vocs-color_background4);transition:background-color .05s}.vocs_CopyButton:focus-visible{background-color:var(--vocs-color_background4);opacity:1;transition:background-color .05s}.vocs_CopyButton:hover:active{background-color:var(--vocs-color_background2)}.vocs_CopyButton[data-copied=true]:hover:active{background-color:var(--vocs-color_background4)}.vocs_Pre:hover .vocs_CopyButton{opacity:1}.vocs_CopyButton_copied{height:12px;width:12px}.vocs_CodeBlock{border:1px solid var(--vocs-color_codeInlineBorder);border-radius:var(--vocs-borderRadius_4)}.vocs_Tabs .vocs_CodeBlock{border:none;margin-left:unset;margin-right:unset}.vocs_Callout_content .vocs_CodeBlock{margin-left:-22px;margin-right:unset;margin-top:-4px}.vocs_CodeBlock code{display:grid;font-size:var(--vocs-fontSize_codeBlock)}.vocs_Callout_content .vocs_CodeBlock code{font-size:var(--vocs-fontSize_calloutCodeBlock)}.vocs_CodeBlock pre{background-color:var(--vocs-color_codeBlockBackground);border-radius:var(--vocs-borderRadius_4);overflow-x:auto;padding:var(--vocs-space_20) var(--vocs-space_0)}.vocs_Callout_content .vocs_CodeBlock pre{background-color:color-mix(in srgb,var(--vocs-color_codeBlockBackground) 65%,transparent)!important;border:none;border-radius:var(--vocs-borderRadius_4);padding:var(--vocs-space_12) var(--vocs-space_0)}.vocs_CodeBlock .line{border-left:2px solid transparent;padding:var(--vocs-space_0) var(--vocs-space_22);line-height:var(--vocs-lineHeight_code)}.vocs_Callout_content .vocs_CodeBlock .line{padding:var(--vocs-space_0) var(--vocs-space_12)}.vocs_CodeBlock .twoslash-popup-info .line{padding:var(--vocs-space_0) var(--vocs-space_4)}.vocs_CodeBlock .twoslash-popup-info-hover .line{display:inline-block;padding:var(--vocs-space_0) var(--vocs-space_8)}.vocs_CodeBlock .twoslash-error-line,.vocs_CodeBlock .twoslash-tag-line{padding:var(--vocs-space_0) var(--vocs-space_22)}.vocs_CodeBlock [data-line-numbers]{counter-reset:line}.vocs_CodeBlock [data-line-numbers]>.line{padding:var(--vocs-space_0) var(--vocs-space_16)}.vocs_CodeBlock [data-line-numbers]>.line:before{content:counter(line);color:var(--vocs-color_lineNumber);display:inline-block;font-size:var(--vocs-fontSize_lineNumber);margin-right:var(--vocs-space_16);text-align:right;width:1rem}.vocs_CodeBlock [data-line-numbers]>.line:not(.diff.remove+.diff.add):before{counter-increment:line}.vocs_CodeBlock [data-line-numbers]>.line.diff:after{margin-left:calc(-1 * var(--vocs-space_4))}.vocs_CodeBlock .highlighted{background-color:var(--vocs-color_codeHighlightBackground);border-left:2px solid var(--vocs-color_codeHighlightBorder);box-sizing:content-box}.vocs_CodeBlock .highlighted-word{border-radius:var(--vocs-borderRadius_2);background-color:var(--vocs-color_codeCharacterHighlightBackground)!important;box-shadow:0 0 0 2px var(--vocs-color_codeCharacterHighlightBackground),0 0 0 3px var(--vocs-color_codeCharacterHighlightBorder)}.vocs_CodeBlock .has-diff{position:relative}.vocs_CodeBlock .line.diff:after{position:absolute;left:var(--vocs-space_8)}.vocs_CodeBlock .line.diff.add{background-color:var(--vocs-color_backgroundGreenTint2)}.vocs_CodeBlock .line.diff.add:after{content:"+";color:var(--vocs-color_textGreen)}.vocs_CodeBlock .line.diff.remove{background-color:var(--vocs-color_backgroundRedTint2);opacity:.6}.vocs_CodeBlock .line.diff.remove>span{filter:grayscale(1)}.vocs_CodeBlock .line.diff.remove:after{content:"-";color:var(--vocs-color_textRed)}.vocs_CodeBlock .has-focused>code>.line:not(.focused),.vocs_CodeBlock .has-focused>code>.twoslash-meta-line:not(.focused){opacity:.3;transition:opacity .2s}.vocs_CodeBlock:hover .has-focused .line:not(.focused),.vocs_CodeBlock:hover .has-focused .twoslash-meta-line:not(.focused){opacity:1;transition:opacity .2s}@media screen and (max-width:720px){.vocs_CodeBlock{border-radius:0;border-right:none;border-left:none;margin-left:calc(-1 * var(--vocs-space_16));margin-right:calc(-1 * var(--vocs-space_16))}.vocs_CodeBlock pre{border-radius:0}.vocs_CodeBlock .line,.vocs_CodeBlock .twoslash-error-line,.vocs_CodeBlock .twoslash-tag-line{padding:0 var(--vocs-space_16)}.vocs_CodeBlock .line.diff:after{left:var(--vocs-space_6)}}.vocs_CodeTitle{align-items:center;background-color:var(--vocs-color_codeTitleBackground);border-bottom:1px solid var(--vocs-color_border);color:var(--vocs-color_text3);display:flex;font-size:var(--vocs-fontSize_14);font-weight:var(--vocs-fontWeight_medium);gap:var(--vocs-space_6);padding:var(--vocs-space_8) var(--vocs-space_24)}.vocs_CodeGroup .vocs_CodeTitle{display:none}@media screen and (max-width:720px){.vocs_CodeTitle{border-radius:0;padding-left:var(--vocs-space_16);padding-right:var(--vocs-space_16)}}.vocs_Strong{font-weight:var(--vocs-fontWeight_semibold);line-height:var(--vocs-lineHeight_paragraph)}.vocs_Content>.vocs_Strong{display:block}.vocs_Callout_content>.vocs_Strong{display:block;margin-bottom:var(--vocs-space_4)}.vocs_Summary{cursor:pointer;line-height:var(--vocs-lineHeight_paragraph)}.vocs_Summary.vocs_Summary:hover{text-decoration:underline}.vocs_Details[open] .vocs_Summary{margin-bottom:var(--vocs-space_4)}.vocs_Callout_content .vocs_Summary{font-weight:var(--vocs-fontWeight_medium)}.vocs_Details .vocs_Summary.vocs_Summary{margin-bottom:0}.vocs_Table{display:block;border-collapse:collapse;overflow-x:auto;margin-bottom:var(--vocs-space_24)}.vocs_TableCell{border:1px solid var(--vocs-color_tableBorder);font-size:var(--vocs-fontSize_td);padding:var(--vocs-space_8) var(--vocs-space_12)}.vocs_TableHeader{border:1px solid var(--vocs-color_tableBorder);background-color:var(--vocs-color_tableHeaderBackground);color:var(--vocs-color_tableHeaderText);font-size:var(--vocs-fontSize_th);font-weight:var(--vocs-fontWeight_medium);padding:var(--vocs-space_8) var(--vocs-space_12);text-align:left}.vocs_TableHeader[align=center]{text-align:center}.vocs_TableHeader[align=right]{text-align:right}.vocs_TableRow{border-top:1px solid var(--vocs-color_tableBorder)}.vocs_TableRow:nth-child(2n){background-color:var(--vocs-color_background2)}.vocs_DocsLayout_content{background:transparent!important}.vocs_Content{height:100%} |
| 1 | + | import{u as i,j as e}from"./index-DO6OtFZH.js";const t={title:"What is Andromeda",description:"undefined"};function r(n){const s={a:"a",code:"code",div:"div",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...i(),...n.components};return e.jsxs(e.Fragment,{children:[e.jsx(s.header,{children:e.jsxs(s.h1,{id:"what-is-andromeda",children:["What is Andromeda",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#what-is-andromeda",children:e.jsx(s.div,{"data-autolink-icon":!0})})]})}),` |
|
| 2 | + | `,e.jsxs(s.p,{children:["Andromeda is a Rust workspace of minimal, self-hosted web apps. Each app compiles to a single binary powered by ",e.jsx(s.a,{href:"https://github.com/tokio-rs/axum",children:"Axum"}),", ",e.jsx(s.a,{href:"https://github.com/rusqlite/rusqlite",children:"SQLite"}),", and ",e.jsx(s.a,{href:"https://github.com/djc/askama",children:"Askama"})," templates."]}),` |
|
| 3 | + | `,e.jsxs(s.h2,{id:"philosophy",children:["Philosophy",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#philosophy",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 4 | + | `,e.jsx(s.p,{children:"Every app in Andromeda follows the same principles:"}),` |
|
| 5 | + | `,e.jsxs(s.ul,{children:[` |
|
| 6 | + | `,e.jsxs(s.li,{children:[e.jsx(s.strong,{children:"Single binary"})," - Each app compiles to one small binary (~7MB) with all assets embedded at compile time"]}),` |
|
| 7 | + | `,e.jsxs(s.li,{children:[e.jsx(s.strong,{children:"Minimal resource usage"})," - Apps average around ~10MB of RAM"]}),` |
|
| 8 | + | `,e.jsxs(s.li,{children:[e.jsx(s.strong,{children:"Self-hosted"})," - You own your data and run it on your own infrastructure"]}),` |
|
| 9 | + | `,e.jsxs(s.li,{children:[e.jsx(s.strong,{children:"Simple deployment"})," - One binary, one optional ",e.jsx(s.code,{children:".env"})," file, no external dependencies"]}),` |
|
| 10 | + | `,e.jsxs(s.li,{children:[e.jsx(s.strong,{children:"Consistent stack"})," - All apps share the same Rust stack so patterns are transferable"]}),` |
|
| 11 | + | `]}),` |
|
| 12 | + | `,e.jsxs(s.h2,{id:"apps",children:["Apps",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#apps",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 13 | + | `,e.jsxs(s.table,{children:[e.jsx(s.thead,{children:e.jsxs(s.tr,{children:[e.jsx(s.th,{children:"App"}),e.jsx(s.th,{children:"Description"})]})}),e.jsxs(s.tbody,{children:[e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.a,{href:"/apps/sipp",children:"Sipp"})}),e.jsx(s.td,{children:"Code sharing with web UI and TUI"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.a,{href:"/apps/feeds",children:"Feeds"})}),e.jsx(s.td,{children:"RSS reader with FreshRSS and OPML support"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.a,{href:"/apps/parcels",children:"Parcels"})}),e.jsx(s.td,{children:"Package tracking (USPS)"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.a,{href:"/apps/jotts",children:"Jotts"})}),e.jsx(s.td,{children:"Markdown notes"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.a,{href:"/apps/og",children:"OG"})}),e.jsx(s.td,{children:"Open Graph tag inspector"})]}),e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.a,{href:"/apps/shrink",children:"Shrink"})}),e.jsx(s.td,{children:"Image compression and resizing"})]})]})]}),` |
|
| 14 | + | `,e.jsxs(s.h2,{id:"shared-crates",children:["Shared Crates",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#shared-crates",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 15 | + | `,e.jsxs(s.table,{children:[e.jsx(s.thead,{children:e.jsxs(s.tr,{children:[e.jsx(s.th,{children:"Crate"}),e.jsx(s.th,{children:"Description"})]})}),e.jsx(s.tbody,{children:e.jsxs(s.tr,{children:[e.jsx(s.td,{children:e.jsx(s.code,{children:"andromeda-auth"})}),e.jsx(s.td,{children:"Session-based password authentication"})]})})]}),` |
|
| 16 | + | `,e.jsxs(s.p,{children:["The ",e.jsx(s.code,{children:"andromeda-auth"})," crate provides a shared authentication layer used across apps that require login, including session cookies and constant-time password verification."]}),` |
|
| 17 | + | `,e.jsxs(s.h2,{id:"license",children:["License",e.jsx(s.a,{"aria-hidden":"true",tabIndex:"-1",href:"#license",children:e.jsx(s.div,{"data-autolink-icon":!0})})]}),` |
|
| 18 | + | `,e.jsx(s.p,{children:e.jsx(s.a,{href:"https://github.com/stevedylandev/andromeda/blob/main/LICENSE",children:"MIT"})})]})}function a(n={}){const{wrapper:s}={...i(),...n.components};return s?e.jsx(s,{...n,children:e.jsx(r,{...n})}):r(n)}export{a as default,t as frontmatter}; |
Binary file — no preview.
| 1 | + | <!doctype html> |
|
| 2 | + | <html lang="en" class="dark" data-vocs> |
|
| 3 | + | <head> |
|
| 4 | + | <meta charset="UTF-8" /> |
|
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
| 6 | + | <script src="/initializeTheme.iife.js"></script><title>Skills – Andromeda</title><meta property="og:type" content="website"/><meta property="og:title" content="Skills"/><meta name="twitter:card" content="summary_large_image"/> |
|
| 7 | + | <script type="module" crossorigin src="/assets/index-DO6OtFZH.js"></script> |
|
| 8 | + | <link rel="stylesheet" crossorigin href="/assets/style-Dg8GuVX0.css"> |
|
| 9 | + | </head> |
|
| 10 | + | <body> |
|
| 11 | + | <span style="display: none;">Are you an LLM? Read <a href="/llms.txt">llms.txt</a> for a summary of the docs, or <a href="/llms-full.txt">llms-full.txt</a> for the full context.</span> |
|
| 12 | + | <div id="app"><div class="vocs_DocsLayout" data-layout="docs"><a class="vocs_SkipLink vocs_utils_visuallyHidden" href="/diy/skills#vocs-content">Skip to content</a><div class="vocs_DocsLayout_gutterLeft"><aside class="vocs_Sidebar vocs_DocsLayout_sidebar"><div><div class="vocs_Sidebar_logoWrapper"><div class="vocs_Sidebar_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div><div class="vocs_Sidebar_divider"></div></div><nav class="vocs_Sidebar_navigation"><div class="vocs_Sidebar_group"><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Intro</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/quickstart" data-discover="true">Quickstart</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/what-is-andromeda" data-discover="true">What is Andromeda</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Apps</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/feeds" data-discover="true">Feeds</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/jotts" data-discover="true">Jotts</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/sipp" data-discover="true">Sipp</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/og" data-discover="true">OG</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/shrink" data-discover="true">Shrink</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/parcels" data-discover="true">Parcels</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">DIY</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/stack" data-discover="true">Stack</a><a data-active="true" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/skills" data-discover="true">Skills</a></div></section></div></nav></div><div class="vocs_Sidebar_footer"><div class="vocs_Sidebar_footerCurtain"></div><div class="vocs_Sidebar_footerContent"></div></div></aside></div><div class="vocs_DocsLayout_gutterTop vocs_DocsLayout_gutterTop_offsetLeftGutter"><div class="vocs_DesktopTopNav"><button class="vocs_DesktopSearch_search" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_4lj_" data-state="closed"><svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-top:2px"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>Search...<div class="vocs_DesktopSearch_searchCommand"><div style="background:currentColor;transform:rotate(45deg);width:1.5px;border-radius:2px;height:100%"></div></div></button><div class="vocs_DesktopTopNav_logoWrapper"><div class="vocs_DesktopTopNav_logo"><a style="align-items:center;display:flex;height:56px;margin-top:4px" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_DesktopTopNav_section"></div><div class="vocs_DesktopTopNav_section"></div></div><div class="vocs_MobileTopNav"><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group"><div class="vocs_MobileTopNav_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_MobileTopNav_group"><nav aria-label="Main" data-orientation="horizontal" dir="ltr" class="vocs_MobileTopNav_navigation vocs_NavigationMenu"><div style="position:relative"><ul data-orientation="horizontal" class="vocs_NavigationMenu_list" dir="ltr"></ul></div></nav><div class="vocs_MobileTopNav_navigation vocs_MobileTopNav_navigation_compact"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_kpj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger vocs_MobileTopNav_navigationItem">Menu<div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group" style="margin-right:-8px"><button class="vocs_MobileSearch_searchButton" type="button" aria-label="Search" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_39j_" data-state="closed"><svg width="21" height="21" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div></div></div></div><div class="vocs_DocsLayout_gutterTopCurtain vocs_DocsLayout_gutterTopCurtain_withSidebar"><div class="vocs_DesktopTopNav_curtain"></div><div class="vocs_MobileTopNav_curtain"><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_qj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger"><div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:13px"><svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 79 48" fill="none"><title>Menu</title><path fill="currentColor" d="M19.528 47.232h40.87c1.952 0 3.515-1.562 3.515-3.564a3.5 3.5 0 0 0-3.516-3.516H19.528a3.501 3.501 0 0 0-3.515 3.516c0 2.002 1.562 3.564 3.515 3.564ZM12.057 27.262h55.81a3.501 3.501 0 0 0 3.516-3.516 3.501 3.501 0 0 0-3.515-3.515h-55.81a3.501 3.501 0 0 0-3.516 3.515 3.501 3.501 0 0 0 3.515 3.516ZM4.391 7.34H75.29c2.002 0 3.515-1.563 3.515-3.516 0-2.002-1.513-3.564-3.515-3.564H4.39C2.438.26.876 1.822.876 3.824A3.501 3.501 0 0 0 4.39 7.34Z"></path></svg></div><div class="vocs_MobileTopNav_menuTitle">Skills</div></button></div></div><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_5aj_" data-state="closed" class="vocs_MobileTopNav_outlineTrigger">On this page<div aria-label="On this page" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Right</title><path d="M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div></div><div class="vocs_DocsLayout_gutterRight vocs_DocsLayout_gutterRight_withSidebar"><aside class="vocs_Outline"><div class="vocs_AiCtaDropdown"><a class="vocs_Button_button vocs_AiCtaDropdown_buttonLeft vocs_AiCtaDropdown_button vocs_Button_button" href="https://chatgpt.com?hints=search&q=" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><div style="width:14px;height:14px"><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24"><title>OpenAI</title><path fill="currentColor" d="M22.282 9.821a6 6 0 0 0-.516-4.91a6.05 6.05 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a6 6 0 0 0-3.998 2.9a6.05 6.05 0 0 0 .743 7.097a5.98 5.98 0 0 0 .51 4.911a6.05 6.05 0 0 0 6.515 2.9A6 6 0 0 0 13.26 24a6.06 6.06 0 0 0 5.772-4.206a6 6 0 0 0 3.997-2.9a6.06 6.06 0 0 0-.747-7.073M13.26 22.43a4.48 4.48 0 0 1-2.876-1.04l.141-.081l4.779-2.758a.8.8 0 0 0 .392-.681v-6.737l2.02 1.168a.07.07 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494M3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085l4.783 2.759a.77.77 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646M2.34 7.896a4.5 4.5 0 0 1 2.366-1.973V11.6a.77.77 0 0 0 .388.677l5.815 3.354l-2.02 1.168a.08.08 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855l-5.833-3.387L15.119 7.2a.08.08 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667m2.01-3.023l-.141-.085l-4.774-2.782a.78.78 0 0 0-.785 0L9.409 9.23V6.897a.07.07 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135l-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08L8.704 5.46a.8.8 0 0 0-.393.681zm1.097-2.365l2.602-1.5l2.607 1.5v2.999l-2.597 1.5l-2.607-1.5Z"></path></svg></div>Ask in ChatGPT</a><button class="vocs_Button_button vocs_AiCtaDropdown_buttonRight vocs_AiCtaDropdown_button vocs_Button_button" type="button" id="radix-_R_9n_" aria-haspopup="menu" aria-expanded="false" data-state="closed"><div style="width:14px;height:14px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></aside></div><div id="vocs-content" class="vocs_DocsLayout_content vocs_DocsLayout_content_withSidebar vocs_DocsLayout_content_withTopNav"><article class="vocs_Content"><header class="vocs_Header"><h1 class="vocs_H1 vocs_Heading"><div id="skills" class="vocs_Heading_slugTarget"></div>Skills<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/skills#skills" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h1></header> |
|
| 13 | + | <p class="vocs_Paragraph">Andromeda apps are scaffolded using <a class="vocs_Anchor" href="https://claude.ai/code" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)">Claude Code</a> with a custom skill called <code class="vocs_Code">rust-crud</code>. This page explains how to use it to build your own apps in the same style.</p> |
|
| 14 | + | <h2 class="vocs_H2 vocs_Heading"><div id="what-is-rust-crud" class="vocs_Heading_slugTarget"></div>What is rust-crud?<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/skills#what-is-rust-crud" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 15 | + | <p class="vocs_Paragraph"><code class="vocs_Code">rust-crud</code> is a Claude Code skill that scaffolds a complete Rust CRUD web application matching the Andromeda stack:</p> |
|
| 16 | + | <ul class="vocs_List vocs_List_unordered"> |
|
| 17 | + | <li class="vocs_ListItem">Axum web server with routing</li> |
|
| 18 | + | <li class="vocs_ListItem">SQLite database with rusqlite</li> |
|
| 19 | + | <li class="vocs_ListItem">Askama HTML templates</li> |
|
| 20 | + | <li class="vocs_ListItem">API key authentication</li> |
|
| 21 | + | <li class="vocs_ListItem">Embedded static assets via rust-embed</li> |
|
| 22 | + | <li class="vocs_ListItem">Dockerfile and docker-compose.yml for deployment</li> |
|
| 23 | + | </ul> |
|
| 24 | + | <h2 class="vocs_H2 vocs_Heading"><div id="using-the-skill" class="vocs_Heading_slugTarget"></div>Using the Skill<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/skills#using-the-skill" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 25 | + | <p class="vocs_Paragraph">In Claude Code, invoke the skill when you want to create a new app:</p> |
|
| 26 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">/rust-crud</span></span></code></pre></div></div> |
|
| 27 | + | <p class="vocs_Paragraph">Describe what you want to build and the skill will generate a complete, working app that follows the same patterns as every other Andromeda app.</p> |
|
| 28 | + | <h2 class="vocs_H2 vocs_Heading"><div id="building-your-own-app" class="vocs_Heading_slugTarget"></div>Building Your Own App<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/skills#building-your-own-app" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 29 | + | <p class="vocs_Paragraph">If you want to add a new app to the workspace manually, follow these steps:</p> |
|
| 30 | + | <h3 class="vocs_H3 vocs_Heading"><div id="1-create-the-app-directory" class="vocs_Heading_slugTarget"></div>1. Create the app directory<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/skills#1-create-the-app-directory" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 31 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">mkdir</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> apps/my-app/src</span></span> |
|
| 32 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">mkdir</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> apps/my-app/templates</span></span> |
|
| 33 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">mkdir</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> apps/my-app/static</span></span></code></pre></div></div> |
|
| 34 | + | <h3 class="vocs_H3 vocs_Heading"><div id="2-add-to-workspace" class="vocs_Heading_slugTarget"></div>2. Add to workspace<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/skills#2-add-to-workspace" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 35 | + | <p class="vocs_Paragraph">Add your app to the root <code class="vocs_Code">Cargo.toml</code> workspace members:</p> |
|
| 36 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">[</span><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">workspace</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">]</span></span> |
|
| 37 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">members = [</span></span> |
|
| 38 | + | <span class="line vocs_Span"><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> "apps/my-app"</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">,</span></span> |
|
| 39 | + | <span class="line vocs_Span"><span style="color:#BDC4CC;--shiki-dark:#BDC4CC" class="vocs_Span"> # ...existing apps</span></span> |
|
| 40 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">]</span></span></code></pre></div></div> |
|
| 41 | + | <h3 class="vocs_H3 vocs_Heading"><div id="3-set-up-cargotoml" class="vocs_Heading_slugTarget"></div>3. Set up Cargo.toml<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/skills#3-set-up-cargotoml" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 42 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">[</span><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">package</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">]</span></span> |
|
| 43 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">name = </span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"my-app"</span></span> |
|
| 44 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">version = </span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"0.1.0"</span></span> |
|
| 45 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">edition = </span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"2021"</span></span> |
|
| 46 | + | <span class="line vocs_Span" data-empty-line="true"> </span> |
|
| 47 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">[</span><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">dependencies</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">]</span></span> |
|
| 48 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">axum = </span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"0.8"</span></span> |
|
| 49 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">tokio = { version = </span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"1"</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">, features = [</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"full"</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">] }</span></span> |
|
| 50 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">rusqlite = { version = </span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"0.32"</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">, features = [</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"bundled"</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">] }</span></span> |
|
| 51 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">askama = </span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"0.12"</span></span> |
|
| 52 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">askama_axum = </span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"0.4"</span></span> |
|
| 53 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">rust-embed = </span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"8"</span></span> |
|
| 54 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">tower-http = { version = </span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"0.6"</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">, features = [</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"cors"</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">] }</span></span> |
|
| 55 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">serde = { version = </span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"1"</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">, features = [</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"derive"</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">] }</span></span> |
|
| 56 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">dotenvy = </span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"0.15"</span></span></code></pre></div></div> |
|
| 57 | + | <h3 class="vocs_H3 vocs_Heading"><div id="4-follow-the-pattern" class="vocs_Heading_slugTarget"></div>4. Follow the pattern<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/skills#4-follow-the-pattern" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 58 | + | <p class="vocs_Paragraph">Use the <a class="vocs_Anchor vocs_Link vocs_Link_accent" href="/diy/stack" data-discover="true">Stack</a> page as a reference for how to structure your <code class="vocs_Code">main.rs</code>, <code class="vocs_Code">server.rs</code>, and <code class="vocs_Code">db.rs</code> files. Look at any existing app in <code class="vocs_Code">apps/</code> for a working example.</p> |
|
| 59 | + | <h3 class="vocs_H3 vocs_Heading"><div id="5-build-and-run" class="vocs_Heading_slugTarget"></div>5. Build and run<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/skills#5-build-and-run" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 60 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> run</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> my-app</span></span></code></pre></div></div></article><footer class="vocs_Footer" data-layout="docs"><div class="vocs_Footer_container"></div></footer></div><div data-bottom-observer="true"></div></div></div> |
|
| 61 | + | </body> |
|
| 62 | + | </html> |
| 1 | + | <!doctype html> |
|
| 2 | + | <html lang="en" class="dark" data-vocs> |
|
| 3 | + | <head> |
|
| 4 | + | <meta charset="UTF-8" /> |
|
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
| 6 | + | <script src="/initializeTheme.iife.js"></script><title>Stack – Andromeda</title><meta property="og:type" content="website"/><meta property="og:title" content="Stack"/><meta name="twitter:card" content="summary_large_image"/> |
|
| 7 | + | <script type="module" crossorigin src="/assets/index-DO6OtFZH.js"></script> |
|
| 8 | + | <link rel="stylesheet" crossorigin href="/assets/style-Dg8GuVX0.css"> |
|
| 9 | + | </head> |
|
| 10 | + | <body> |
|
| 11 | + | <span style="display: none;">Are you an LLM? Read <a href="/llms.txt">llms.txt</a> for a summary of the docs, or <a href="/llms-full.txt">llms-full.txt</a> for the full context.</span> |
|
| 12 | + | <div id="app"><div class="vocs_DocsLayout" data-layout="docs"><a class="vocs_SkipLink vocs_utils_visuallyHidden" href="/diy/stack#vocs-content">Skip to content</a><div class="vocs_DocsLayout_gutterLeft"><aside class="vocs_Sidebar vocs_DocsLayout_sidebar"><div><div class="vocs_Sidebar_logoWrapper"><div class="vocs_Sidebar_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div><div class="vocs_Sidebar_divider"></div></div><nav class="vocs_Sidebar_navigation"><div class="vocs_Sidebar_group"><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Intro</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/quickstart" data-discover="true">Quickstart</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/what-is-andromeda" data-discover="true">What is Andromeda</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Apps</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/feeds" data-discover="true">Feeds</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/jotts" data-discover="true">Jotts</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/sipp" data-discover="true">Sipp</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/og" data-discover="true">OG</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/shrink" data-discover="true">Shrink</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/parcels" data-discover="true">Parcels</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">DIY</div></div><div class="vocs_Sidebar_items"><a data-active="true" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/stack" data-discover="true">Stack</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/skills" data-discover="true">Skills</a></div></section></div></nav></div><div class="vocs_Sidebar_footer"><div class="vocs_Sidebar_footerCurtain"></div><div class="vocs_Sidebar_footerContent"></div></div></aside></div><div class="vocs_DocsLayout_gutterTop vocs_DocsLayout_gutterTop_offsetLeftGutter"><div class="vocs_DesktopTopNav"><button class="vocs_DesktopSearch_search" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_4lj_" data-state="closed"><svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-top:2px"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>Search...<div class="vocs_DesktopSearch_searchCommand"><div style="background:currentColor;transform:rotate(45deg);width:1.5px;border-radius:2px;height:100%"></div></div></button><div class="vocs_DesktopTopNav_logoWrapper"><div class="vocs_DesktopTopNav_logo"><a style="align-items:center;display:flex;height:56px;margin-top:4px" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_DesktopTopNav_section"></div><div class="vocs_DesktopTopNav_section"></div></div><div class="vocs_MobileTopNav"><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group"><div class="vocs_MobileTopNav_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_MobileTopNav_group"><nav aria-label="Main" data-orientation="horizontal" dir="ltr" class="vocs_MobileTopNav_navigation vocs_NavigationMenu"><div style="position:relative"><ul data-orientation="horizontal" class="vocs_NavigationMenu_list" dir="ltr"></ul></div></nav><div class="vocs_MobileTopNav_navigation vocs_MobileTopNav_navigation_compact"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_kpj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger vocs_MobileTopNav_navigationItem">Menu<div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group" style="margin-right:-8px"><button class="vocs_MobileSearch_searchButton" type="button" aria-label="Search" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_39j_" data-state="closed"><svg width="21" height="21" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div></div></div></div><div class="vocs_DocsLayout_gutterTopCurtain vocs_DocsLayout_gutterTopCurtain_withSidebar"><div class="vocs_DesktopTopNav_curtain"></div><div class="vocs_MobileTopNav_curtain"><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_qj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger"><div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:13px"><svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 79 48" fill="none"><title>Menu</title><path fill="currentColor" d="M19.528 47.232h40.87c1.952 0 3.515-1.562 3.515-3.564a3.5 3.5 0 0 0-3.516-3.516H19.528a3.501 3.501 0 0 0-3.515 3.516c0 2.002 1.562 3.564 3.515 3.564ZM12.057 27.262h55.81a3.501 3.501 0 0 0 3.516-3.516 3.501 3.501 0 0 0-3.515-3.515h-55.81a3.501 3.501 0 0 0-3.516 3.515 3.501 3.501 0 0 0 3.515 3.516ZM4.391 7.34H75.29c2.002 0 3.515-1.563 3.515-3.516 0-2.002-1.513-3.564-3.515-3.564H4.39C2.438.26.876 1.822.876 3.824A3.501 3.501 0 0 0 4.39 7.34Z"></path></svg></div><div class="vocs_MobileTopNav_menuTitle">Stack</div></button></div></div><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_5aj_" data-state="closed" class="vocs_MobileTopNav_outlineTrigger">On this page<div aria-label="On this page" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Right</title><path d="M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div></div><div class="vocs_DocsLayout_gutterRight vocs_DocsLayout_gutterRight_withSidebar"><aside class="vocs_Outline"><div class="vocs_AiCtaDropdown"><a class="vocs_Button_button vocs_AiCtaDropdown_buttonLeft vocs_AiCtaDropdown_button vocs_Button_button" href="https://chatgpt.com?hints=search&q=" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><div style="width:14px;height:14px"><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24"><title>OpenAI</title><path fill="currentColor" d="M22.282 9.821a6 6 0 0 0-.516-4.91a6.05 6.05 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a6 6 0 0 0-3.998 2.9a6.05 6.05 0 0 0 .743 7.097a5.98 5.98 0 0 0 .51 4.911a6.05 6.05 0 0 0 6.515 2.9A6 6 0 0 0 13.26 24a6.06 6.06 0 0 0 5.772-4.206a6 6 0 0 0 3.997-2.9a6.06 6.06 0 0 0-.747-7.073M13.26 22.43a4.48 4.48 0 0 1-2.876-1.04l.141-.081l4.779-2.758a.8.8 0 0 0 .392-.681v-6.737l2.02 1.168a.07.07 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494M3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085l4.783 2.759a.77.77 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646M2.34 7.896a4.5 4.5 0 0 1 2.366-1.973V11.6a.77.77 0 0 0 .388.677l5.815 3.354l-2.02 1.168a.08.08 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855l-5.833-3.387L15.119 7.2a.08.08 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667m2.01-3.023l-.141-.085l-4.774-2.782a.78.78 0 0 0-.785 0L9.409 9.23V6.897a.07.07 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135l-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08L8.704 5.46a.8.8 0 0 0-.393.681zm1.097-2.365l2.602-1.5l2.607 1.5v2.999l-2.597 1.5l-2.607-1.5Z"></path></svg></div>Ask in ChatGPT</a><button class="vocs_Button_button vocs_AiCtaDropdown_buttonRight vocs_AiCtaDropdown_button vocs_Button_button" type="button" id="radix-_R_9n_" aria-haspopup="menu" aria-expanded="false" data-state="closed"><div style="width:14px;height:14px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></aside></div><div id="vocs-content" class="vocs_DocsLayout_content vocs_DocsLayout_content_withSidebar vocs_DocsLayout_content_withTopNav"><article class="vocs_Content"><header class="vocs_Header"><h1 class="vocs_H1 vocs_Heading"><div id="stack" class="vocs_Heading_slugTarget"></div>Stack<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/stack#stack" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h1></header> |
|
| 13 | + | <p class="vocs_Paragraph">Every app in Andromeda is built on the same Rust stack. This page covers the core dependencies and how they fit together.</p> |
|
| 14 | + | <h2 class="vocs_H2 vocs_Heading"><div id="core-dependencies" class="vocs_Heading_slugTarget"></div>Core Dependencies<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/stack#core-dependencies" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 15 | + | <h3 class="vocs_H3 vocs_Heading"><div id="axum" class="vocs_Heading_slugTarget"></div>Axum<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/stack#axum" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 16 | + | <p class="vocs_Paragraph"><a class="vocs_Anchor" href="https://github.com/tokio-rs/axum" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)">Axum</a> is the web framework powering every app. It provides routing, request extraction, middleware, and response handling. All apps follow a similar pattern:</p> |
|
| 17 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FF9492;--shiki-dark:#FF9492" class="vocs_Span">let</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span"> app </span><span style="color:#FF9492;--shiki-dark:#FF9492" class="vocs_Span">=</span><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span"> Router</span><span style="color:#FF9492;--shiki-dark:#FF9492" class="vocs_Span">::</span><span style="color:#DBB7FF;--shiki-dark:#DBB7FF" class="vocs_Span">new</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">()</span></span> |
|
| 18 | + | <span class="line vocs_Span"><span style="color:#FF9492;--shiki-dark:#FF9492" class="vocs_Span"> .</span><span style="color:#DBB7FF;--shiki-dark:#DBB7FF" class="vocs_Span">route</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">(</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"/"</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">, </span><span style="color:#DBB7FF;--shiki-dark:#DBB7FF" class="vocs_Span">get</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">(index))</span></span> |
|
| 19 | + | <span class="line vocs_Span"><span style="color:#FF9492;--shiki-dark:#FF9492" class="vocs_Span"> .</span><span style="color:#DBB7FF;--shiki-dark:#DBB7FF" class="vocs_Span">route</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">(</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">"/api/items"</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">, </span><span style="color:#DBB7FF;--shiki-dark:#DBB7FF" class="vocs_Span">post</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">(create_item))</span></span> |
|
| 20 | + | <span class="line vocs_Span"><span style="color:#FF9492;--shiki-dark:#FF9492" class="vocs_Span"> .</span><span style="color:#DBB7FF;--shiki-dark:#DBB7FF" class="vocs_Span">with_state</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">(app_state);</span></span></code></pre></div></div> |
|
| 21 | + | <h3 class="vocs_H3 vocs_Heading"><div id="sqlite-rusqlite" class="vocs_Heading_slugTarget"></div>SQLite (rusqlite)<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/stack#sqlite-rusqlite" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 22 | + | <p class="vocs_Paragraph"><a class="vocs_Anchor" href="https://github.com/rusqlite/rusqlite" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)">rusqlite</a> provides the storage layer. Each app creates its own SQLite database file, keeping data local and portable. No external database server needed.</p> |
|
| 23 | + | <h3 class="vocs_H3 vocs_Heading"><div id="askama" class="vocs_Heading_slugTarget"></div>Askama<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/stack#askama" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 24 | + | <p class="vocs_Paragraph"><a class="vocs_Anchor" href="https://github.com/djc/askama" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)">Askama</a> handles HTML templating with compile-time checked templates. Templates live in a <code class="vocs_Code">templates/</code> directory and are type-safe Rust structs:</p> |
|
| 25 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">#[derive(</span><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">Template</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">)]</span></span> |
|
| 26 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">#[template(path </span><span style="color:#FF9492;--shiki-dark:#FF9492" class="vocs_Span">=</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> "index.html"</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">)]</span></span> |
|
| 27 | + | <span class="line vocs_Span"><span style="color:#FF9492;--shiki-dark:#FF9492" class="vocs_Span">struct</span><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span"> IndexTemplate</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span"> {</span></span> |
|
| 28 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span"> items</span><span style="color:#FF9492;--shiki-dark:#FF9492" class="vocs_Span">:</span><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span"> Vec</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span"><</span><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">Item</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">>,</span></span> |
|
| 29 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">}</span></span></code></pre></div></div> |
|
| 30 | + | <h3 class="vocs_H3 vocs_Heading"><div id="rust-embed" class="vocs_Heading_slugTarget"></div>rust-embed<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/stack#rust-embed" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 31 | + | <p class="vocs_Paragraph"><a class="vocs_Anchor" href="https://github.com/pyrossh/rust-embed" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)">rust-embed</a> embeds static assets (CSS, fonts, images) directly into the binary at compile time. This is what makes each app a single, self-contained binary with no external file dependencies.</p> |
|
| 32 | + | <h3 class="vocs_H3 vocs_Heading"><div id="tokio" class="vocs_Heading_slugTarget"></div>Tokio<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/stack#tokio" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h3> |
|
| 33 | + | <p class="vocs_Paragraph"><a class="vocs_Anchor" href="https://tokio.rs" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)">Tokio</a> provides the async runtime that Axum runs on.</p> |
|
| 34 | + | <h2 class="vocs_H2 vocs_Heading"><div id="shared-crate-andromeda-auth" class="vocs_Heading_slugTarget"></div>Shared Crate: andromeda-auth<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/stack#shared-crate-andromeda-auth" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 35 | + | <p class="vocs_Paragraph">The <code class="vocs_Code">andromeda-auth</code> crate provides session-based password authentication used across apps that require login. It handles:</p> |
|
| 36 | + | <ul class="vocs_List vocs_List_unordered"> |
|
| 37 | + | <li class="vocs_ListItem">Constant-time password verification</li> |
|
| 38 | + | <li class="vocs_ListItem">Session cookie management</li> |
|
| 39 | + | <li class="vocs_ListItem">Secure cookie configuration via <code class="vocs_Code">COOKIE_SECURE</code> env var</li> |
|
| 40 | + | </ul> |
|
| 41 | + | <h2 class="vocs_H2 vocs_Heading"><div id="app-pattern" class="vocs_Heading_slugTarget"></div>App Pattern<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/diy/stack#app-pattern" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 42 | + | <p class="vocs_Paragraph">Every app follows a consistent structure:</p> |
|
| 43 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">app/</span></span> |
|
| 44 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── src/</span></span> |
|
| 45 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── main.rs # Entry point, env vars, starts server</span></span> |
|
| 46 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── server.rs # Axum routes and handlers</span></span> |
|
| 47 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ ├── db.rs # SQLite database layer</span></span> |
|
| 48 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">│ └── auth.rs # Authentication (if needed)</span></span> |
|
| 49 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── templates/ # Askama HTML templates</span></span> |
|
| 50 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── static/ # Fonts, favicons, styles</span></span> |
|
| 51 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">├── Dockerfile</span></span> |
|
| 52 | + | <span class="line vocs_Span"><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">└── docker-compose.yml</span></span></code></pre></div></div> |
|
| 53 | + | <p class="vocs_Paragraph">This consistency means once you understand one app, you can navigate any of them.</p></article><footer class="vocs_Footer" data-layout="docs"><div class="vocs_Footer_container"></div></footer></div><div data-bottom-observer="true"></div></div></div> |
|
| 54 | + | </body> |
|
| 55 | + | </html> |
| 1 | + | <!doctype html> |
|
| 2 | + | <html lang="en" class="dark" data-vocs> |
|
| 3 | + | <head> |
|
| 4 | + | <meta charset="UTF-8" /> |
|
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
| 6 | + | <script src="/initializeTheme.iife.js"></script><title>Andromeda</title><meta name="description"/><meta property="og:type" content="website"/><meta property="og:title" content="Andromeda"/><meta property="og:description"/><meta name="twitter:card" content="summary_large_image"/> |
|
| 7 | + | <script type="module" crossorigin src="/assets/index-DO6OtFZH.js"></script> |
|
| 8 | + | <link rel="stylesheet" crossorigin href="/assets/style-Dg8GuVX0.css"> |
|
| 9 | + | </head> |
|
| 10 | + | <body> |
|
| 11 | + | <span style="display: none;">Are you an LLM? Read <a href="/llms.txt">llms.txt</a> for a summary of the docs, or <a href="/llms-full.txt">llms-full.txt</a> for the full context.</span> |
|
| 12 | + | <div id="app"><div class="vocs_DocsLayout" data-layout="landing"><a class="vocs_SkipLink vocs_utils_visuallyHidden" href="/#vocs-content">Skip to content</a><div class="vocs_DocsLayout_gutterTop vocs_DocsLayout_gutterTop_sticky"><div class="vocs_DesktopTopNav vocs_DesktopTopNav_withLogo"><button class="vocs_DesktopSearch_search" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_4lj_" data-state="closed"><svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-top:2px"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>Search...<div class="vocs_DesktopSearch_searchCommand"><div style="background:currentColor;transform:rotate(45deg);width:1.5px;border-radius:2px;height:100%"></div></div></button><div class="vocs_DesktopTopNav_logoWrapper"><div class="vocs_DesktopTopNav_logo"><a style="align-items:center;display:flex;height:56px;margin-top:4px" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_DesktopTopNav_section"></div><div class="vocs_DesktopTopNav_section"></div></div><div class="vocs_MobileTopNav"><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group"><div class="vocs_MobileTopNav_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_MobileTopNav_group"><nav aria-label="Main" data-orientation="horizontal" dir="ltr" class="vocs_MobileTopNav_navigation vocs_NavigationMenu"><div style="position:relative"><ul data-orientation="horizontal" class="vocs_NavigationMenu_list" dir="ltr"></ul></div></nav><div class="vocs_MobileTopNav_navigation vocs_MobileTopNav_navigation_compact"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_kpj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger vocs_MobileTopNav_navigationItem"><div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 79 48" fill="none"><title>Menu</title><path fill="currentColor" d="M19.528 47.232h40.87c1.952 0 3.515-1.562 3.515-3.564a3.5 3.5 0 0 0-3.516-3.516H19.528a3.501 3.501 0 0 0-3.515 3.516c0 2.002 1.562 3.564 3.515 3.564ZM12.057 27.262h55.81a3.501 3.501 0 0 0 3.516-3.516 3.501 3.501 0 0 0-3.515-3.515h-55.81a3.501 3.501 0 0 0-3.516 3.515 3.501 3.501 0 0 0 3.515 3.516ZM4.391 7.34H75.29c2.002 0 3.515-1.563 3.515-3.516 0-2.002-1.513-3.564-3.515-3.564H4.39C2.438.26.876 1.822.876 3.824A3.501 3.501 0 0 0 4.39 7.34Z"></path></svg></div></button></div></div></div><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group" style="margin-right:-8px"><button class="vocs_MobileSearch_searchButton" type="button" aria-label="Search" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_39j_" data-state="closed"><svg width="21" height="21" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div></div></div></div><div class="vocs_DocsLayout_gutterTopCurtain vocs_DocsLayout_gutterTopCurtain_hidden"><div class="vocs_DesktopTopNav_curtain"></div><div class="vocs_MobileTopNav_curtain"><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"></div></div><div class="vocs_MobileTopNav_curtainGroup"></div></div></div><div id="vocs-content" class="vocs_DocsLayout_content vocs_DocsLayout_content_withTopNav" style="--vocs-content_horizontalPadding:0px;--vocs-content_width:100%;--vocs-content_verticalPadding:0px"><article class="vocs_Content"><main class="flex w-full sm:h-[85vh] min-h-[85vh] mt-6 mx-auto flex-col items-center justify-center gap-12 p-4 relative" style="background-image:url('/bg.png');background-position:center;background-repeat:no-repeat;background-size:cover;z-index:0"><div class="absolute inset-0 pointer-events-none" style="background-color:rgba(18, 17, 19, 0.7);z-index:-1"></div><div class="flex flex-col items-center gap-12"><h1 class="text-center sm:text-6xl text-4xl font-black" style="font-family:'CommitMono', monospace">Andromeda</h1><h3 class="text-center sm:text-2xl text-lg font-semibold" style="font-family:'CommitMono', monospace">Minimal, self-hosted personal software in Rust</h3></div><div class="flex items-center gap-4"><a href="/quickstart" class="inline-flex items-center justify-center px-4 py-2 text-sm font-medium rounded-md border border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-offset-2 hover:opacity-90 hover:opacity-90 focus:ring-orange-400 text-zinc-900 bg-[#ffb757]">Get Started</a><a href="https://github.com/stevedylandev/andromeda" class="inline-flex items-center justify-center px-4 py-2 text-sm font-medium rounded-md border border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-offset-2 hover:opacity-90 bg-zinc-900! text-zinc-200! hover:bg-zinc-800! focus:ring-gray-500!">GitHub</a></div></main></article><footer class="vocs_Footer" data-layout="landing"></footer></div><div data-bottom-observer="true"></div></div></div> |
|
| 13 | + | </body> |
|
| 14 | + | </html> |
| 1 | + | (function(){"use strict";const e=window.matchMedia("(prefers-color-scheme: dark)");if(!(document.documentElement.classList.contains("dark")||document.documentElement.classList.contains("light"))){const t=localStorage.getItem("vocs.theme");(t||(e.matches?"dark":"light"))==="dark"&&document.documentElement.classList.add("dark"),t||e.addEventListener("change",({matches:s})=>{s?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")})}})(); |
| 1 | + | # Andromeda |
|
| 2 | + | ||
| 3 | + | ## Quickstart |
|
| 4 | + | ||
| 5 | + | Get up and running with any Andromeda app in minutes. |
|
| 6 | + | ||
| 7 | + | ### Prerequisites |
|
| 8 | + | ||
| 9 | + | Make sure [Rust](https://www.rust-lang.org/tools/install) is installed: |
|
| 10 | + | ||
| 11 | + | ```bash |
|
| 12 | + | rustc --version |
|
| 13 | + | ``` |
|
| 14 | + | ||
| 15 | + | ### Clone the Workspace |
|
| 16 | + | ||
| 17 | + | ```bash |
|
| 18 | + | git clone https://github.com/stevedylandev/andromeda.git |
|
| 19 | + | cd andromeda |
|
| 20 | + | ``` |
|
| 21 | + | ||
| 22 | + | ### Build All Apps |
|
| 23 | + | ||
| 24 | + | ```bash |
|
| 25 | + | cargo build --release |
|
| 26 | + | ``` |
|
| 27 | + | ||
| 28 | + | ### Run a Specific App |
|
| 29 | + | ||
| 30 | + | Each app is a workspace member. Run any of them with `cargo run -p`: |
|
| 31 | + | ||
| 32 | + | ```bash |
|
| 33 | + | cargo run -p sipp -- server --port 3000 |
|
| 34 | + | cargo run -p feeds |
|
| 35 | + | cargo run -p parcels |
|
| 36 | + | cargo run -p jotts |
|
| 37 | + | cargo run -p og |
|
| 38 | + | cargo run -p shrink |
|
| 39 | + | ``` |
|
| 40 | + | ||
| 41 | + | Most apps start on `http://localhost:3000` by default. Check each app's page for specific environment variables and configuration. |
|
| 42 | + | ||
| 43 | + | ### Environment Variables |
|
| 44 | + | ||
| 45 | + | Most apps use a `.env` file for configuration. Copy the example file and fill in your values: |
|
| 46 | + | ||
| 47 | + | ```bash |
|
| 48 | + | cp apps/<app-name>/.env.example .env |
|
| 49 | + | ``` |
|
| 50 | + | ||
| 51 | + | ### Deployment |
|
| 52 | + | ||
| 53 | + | Every app compiles to a single binary with embedded assets, making deployment straightforward. Each app supports: |
|
| 54 | + | ||
| 55 | + | * **Railway** - one-click deploy buttons on each app's page |
|
| 56 | + | * **Docker** - `docker compose up -d` |
|
| 57 | + | * **Binary** - copy the binary to your server and run it directly |
|
| 58 | + | ||
| 59 | + | ||
| 60 | + | ## What is Andromeda |
|
| 61 | + | ||
| 62 | + | Andromeda is a Rust workspace of minimal, self-hosted web apps. Each app compiles to a single binary powered by [Axum](https://github.com/tokio-rs/axum), [SQLite](https://github.com/rusqlite/rusqlite), and [Askama](https://github.com/djc/askama) templates. |
|
| 63 | + | ||
| 64 | + | ### Philosophy |
|
| 65 | + | ||
| 66 | + | Every app in Andromeda follows the same principles: |
|
| 67 | + | ||
| 68 | + | * **Single binary** - Each app compiles to one small binary (\~7MB) with all assets embedded at compile time |
|
| 69 | + | * **Minimal resource usage** - Apps average around \~10MB of RAM |
|
| 70 | + | * **Self-hosted** - You own your data and run it on your own infrastructure |
|
| 71 | + | * **Simple deployment** - One binary, one optional `.env` file, no external dependencies |
|
| 72 | + | * **Consistent stack** - All apps share the same Rust stack so patterns are transferable |
|
| 73 | + | ||
| 74 | + | ### Apps |
|
| 75 | + | ||
| 76 | + | | App | Description | |
|
| 77 | + | | ------------------------ | ----------------------------------------- | |
|
| 78 | + | | [Sipp](/apps/sipp) | Code sharing with web UI and TUI | |
|
| 79 | + | | [Feeds](/apps/feeds) | RSS reader with FreshRSS and OPML support | |
|
| 80 | + | | [Parcels](/apps/parcels) | Package tracking (USPS) | |
|
| 81 | + | | [Jotts](/apps/jotts) | Markdown notes | |
|
| 82 | + | | [OG](/apps/og) | Open Graph tag inspector | |
|
| 83 | + | | [Shrink](/apps/shrink) | Image compression and resizing | |
|
| 84 | + | ||
| 85 | + | ### Shared Crates |
|
| 86 | + | ||
| 87 | + | | Crate | Description | |
|
| 88 | + | | ---------------- | ------------------------------------- | |
|
| 89 | + | | `andromeda-auth` | Session-based password authentication | |
|
| 90 | + | ||
| 91 | + | The `andromeda-auth` crate provides a shared authentication layer used across apps that require login, including session cookies and constant-time password verification. |
|
| 92 | + | ||
| 93 | + | ### License |
|
| 94 | + | ||
| 95 | + | [MIT](https://github.com/stevedylandev/andromeda/blob/main/LICENSE) |
|
| 96 | + | ||
| 97 | + | ||
| 98 | + | ## Skills |
|
| 99 | + | ||
| 100 | + | Andromeda apps are scaffolded using [Claude Code](https://claude.ai/code) with a custom skill called `rust-crud`. This page explains how to use it to build your own apps in the same style. |
|
| 101 | + | ||
| 102 | + | ### What is rust-crud? |
|
| 103 | + | ||
| 104 | + | `rust-crud` is a Claude Code skill that scaffolds a complete Rust CRUD web application matching the Andromeda stack: |
|
| 105 | + | ||
| 106 | + | * Axum web server with routing |
|
| 107 | + | * SQLite database with rusqlite |
|
| 108 | + | * Askama HTML templates |
|
| 109 | + | * API key authentication |
|
| 110 | + | * Embedded static assets via rust-embed |
|
| 111 | + | * Dockerfile and docker-compose.yml for deployment |
|
| 112 | + | ||
| 113 | + | ### Using the Skill |
|
| 114 | + | ||
| 115 | + | In Claude Code, invoke the skill when you want to create a new app: |
|
| 116 | + | ||
| 117 | + | ``` |
|
| 118 | + | /rust-crud |
|
| 119 | + | ``` |
|
| 120 | + | ||
| 121 | + | Describe what you want to build and the skill will generate a complete, working app that follows the same patterns as every other Andromeda app. |
|
| 122 | + | ||
| 123 | + | ### Building Your Own App |
|
| 124 | + | ||
| 125 | + | If you want to add a new app to the workspace manually, follow these steps: |
|
| 126 | + | ||
| 127 | + | #### 1. Create the app directory |
|
| 128 | + | ||
| 129 | + | ```bash |
|
| 130 | + | mkdir -p apps/my-app/src |
|
| 131 | + | mkdir -p apps/my-app/templates |
|
| 132 | + | mkdir -p apps/my-app/static |
|
| 133 | + | ``` |
|
| 134 | + | ||
| 135 | + | #### 2. Add to workspace |
|
| 136 | + | ||
| 137 | + | Add your app to the root `Cargo.toml` workspace members: |
|
| 138 | + | ||
| 139 | + | ```toml |
|
| 140 | + | [workspace] |
|
| 141 | + | members = [ |
|
| 142 | + | "apps/my-app", |
|
| 143 | + | # ...existing apps |
|
| 144 | + | ] |
|
| 145 | + | ``` |
|
| 146 | + | ||
| 147 | + | #### 3. Set up Cargo.toml |
|
| 148 | + | ||
| 149 | + | ```toml |
|
| 150 | + | [package] |
|
| 151 | + | name = "my-app" |
|
| 152 | + | version = "0.1.0" |
|
| 153 | + | edition = "2021" |
|
| 154 | + | ||
| 155 | + | [dependencies] |
|
| 156 | + | axum = "0.8" |
|
| 157 | + | tokio = { version = "1", features = ["full"] } |
|
| 158 | + | rusqlite = { version = "0.32", features = ["bundled"] } |
|
| 159 | + | askama = "0.12" |
|
| 160 | + | askama_axum = "0.4" |
|
| 161 | + | rust-embed = "8" |
|
| 162 | + | tower-http = { version = "0.6", features = ["cors"] } |
|
| 163 | + | serde = { version = "1", features = ["derive"] } |
|
| 164 | + | dotenvy = "0.15" |
|
| 165 | + | ``` |
|
| 166 | + | ||
| 167 | + | #### 4. Follow the pattern |
|
| 168 | + | ||
| 169 | + | Use the [Stack](/diy/stack) page as a reference for how to structure your `main.rs`, `server.rs`, and `db.rs` files. Look at any existing app in `apps/` for a working example. |
|
| 170 | + | ||
| 171 | + | #### 5. Build and run |
|
| 172 | + | ||
| 173 | + | ```bash |
|
| 174 | + | cargo run -p my-app |
|
| 175 | + | ``` |
|
| 176 | + | ||
| 177 | + | ||
| 178 | + | ## Stack |
|
| 179 | + | ||
| 180 | + | Every app in Andromeda is built on the same Rust stack. This page covers the core dependencies and how they fit together. |
|
| 181 | + | ||
| 182 | + | ### Core Dependencies |
|
| 183 | + | ||
| 184 | + | #### Axum |
|
| 185 | + | ||
| 186 | + | [Axum](https://github.com/tokio-rs/axum) is the web framework powering every app. It provides routing, request extraction, middleware, and response handling. All apps follow a similar pattern: |
|
| 187 | + | ||
| 188 | + | ```rust |
|
| 189 | + | let app = Router::new() |
|
| 190 | + | .route("/", get(index)) |
|
| 191 | + | .route("/api/items", post(create_item)) |
|
| 192 | + | .with_state(app_state); |
|
| 193 | + | ``` |
|
| 194 | + | ||
| 195 | + | #### SQLite (rusqlite) |
|
| 196 | + | ||
| 197 | + | [rusqlite](https://github.com/rusqlite/rusqlite) provides the storage layer. Each app creates its own SQLite database file, keeping data local and portable. No external database server needed. |
|
| 198 | + | ||
| 199 | + | #### Askama |
|
| 200 | + | ||
| 201 | + | [Askama](https://github.com/djc/askama) handles HTML templating with compile-time checked templates. Templates live in a `templates/` directory and are type-safe Rust structs: |
|
| 202 | + | ||
| 203 | + | ```rust |
|
| 204 | + | #[derive(Template)] |
|
| 205 | + | #[template(path = "index.html")] |
|
| 206 | + | struct IndexTemplate { |
|
| 207 | + | items: Vec<Item>, |
|
| 208 | + | } |
|
| 209 | + | ``` |
|
| 210 | + | ||
| 211 | + | #### rust-embed |
|
| 212 | + | ||
| 213 | + | [rust-embed](https://github.com/pyrossh/rust-embed) embeds static assets (CSS, fonts, images) directly into the binary at compile time. This is what makes each app a single, self-contained binary with no external file dependencies. |
|
| 214 | + | ||
| 215 | + | #### Tokio |
|
| 216 | + | ||
| 217 | + | [Tokio](https://tokio.rs) provides the async runtime that Axum runs on. |
|
| 218 | + | ||
| 219 | + | ### Shared Crate: andromeda-auth |
|
| 220 | + | ||
| 221 | + | The `andromeda-auth` crate provides session-based password authentication used across apps that require login. It handles: |
|
| 222 | + | ||
| 223 | + | * Constant-time password verification |
|
| 224 | + | * Session cookie management |
|
| 225 | + | * Secure cookie configuration via `COOKIE_SECURE` env var |
|
| 226 | + | ||
| 227 | + | ### App Pattern |
|
| 228 | + | ||
| 229 | + | Every app follows a consistent structure: |
|
| 230 | + | ||
| 231 | + | ``` |
|
| 232 | + | app/ |
|
| 233 | + | ├── src/ |
|
| 234 | + | │ ├── main.rs # Entry point, env vars, starts server |
|
| 235 | + | │ ├── server.rs # Axum routes and handlers |
|
| 236 | + | │ ├── db.rs # SQLite database layer |
|
| 237 | + | │ └── auth.rs # Authentication (if needed) |
|
| 238 | + | ├── templates/ # Askama HTML templates |
|
| 239 | + | ├── static/ # Fonts, favicons, styles |
|
| 240 | + | ├── Dockerfile |
|
| 241 | + | └── docker-compose.yml |
|
| 242 | + | ``` |
|
| 243 | + | ||
| 244 | + | This consistency means once you understand one app, you can navigate any of them. |
|
| 245 | + | ||
| 246 | + | ||
| 247 | + | ## Feeds |
|
| 248 | + | ||
| 249 | + | Minimal RSS Feeds |
|
| 250 | + | ||
| 251 | + | ### Overview |
|
| 252 | + | ||
| 253 | + | Feeds is a minimal RSS reader that mimics the original experience of RSS. It's just a list of posts. No categories, no marking a post read or unread, and there is no in-app reading. With this approach you have to read the post on the author's personal website and experience it in its original context. |
|
| 254 | + | ||
| 255 | + | * Single Rust binary with embedded assets |
|
| 256 | + | * Multiple feed sources: URL params, OPML file, or FreshRSS API |
|
| 257 | + | * Password-protected admin panel for managing subscriptions |
|
| 258 | + | * Feeds API with JSON and OPML export |
|
| 259 | + | * Dark themed UI with Commit Mono font |
|
| 260 | + | ||
| 261 | + | ### Quickstart |
|
| 262 | + | ||
| 263 | + | ```bash |
|
| 264 | + | git clone https://github.com/stevedylandev/andromeda.git |
|
| 265 | + | cd andromeda |
|
| 266 | + | cargo run -p feeds |
|
| 267 | + | # Server running on http://localhost:3000 |
|
| 268 | + | ``` |
|
| 269 | + | ||
| 270 | + | #### Environment Variables |
|
| 271 | + | ||
| 272 | + | | Variable | Description | Default | |
|
| 273 | + | | ------------------- | ----------------------------- | ------- | |
|
| 274 | + | | `FRESHRSS_URL` | URL of your FreshRSS instance | -- | |
|
| 275 | + | | `FRESHRSS_USERNAME` | FreshRSS username | -- | |
|
| 276 | + | | `FRESHRSS_PASSWORD` | FreshRSS password | -- | |
|
| 277 | + | | `ADMIN_PASSWORD` | Password for the admin panel | -- | |
|
| 278 | + | | `COOKIE_SECURE` | Enable HTTPS-only cookies | `false` | |
|
| 279 | + | ||
| 280 | + | ### Usage |
|
| 281 | + | ||
| 282 | + | There are several built-in ways to source RSS feeds. |
|
| 283 | + | ||
| 284 | + | #### URL Query Param |
|
| 285 | + | ||
| 286 | + | Once you have the app running you can add the following to the URL to source an RSS feed: |
|
| 287 | + | ||
| 288 | + | ``` |
|
| 289 | + | ?url=https://bearblog.dev/discover/feed/ |
|
| 290 | + | ``` |
|
| 291 | + | ||
| 292 | + | You can also add multiple URLs by using commas to separate them: |
|
| 293 | + | ||
| 294 | + | ``` |
|
| 295 | + | ?urls=https://bearblog.dev/discover/feed/,https://bearblog.stevedylan.dev/feed/ |
|
| 296 | + | ``` |
|
| 297 | + | ||
| 298 | + | #### OPML File |
|
| 299 | + | ||
| 300 | + | If you save a `feeds.opml` file in the root of the project the app will automatically source it and fetch the posts for the feeds inside. |
|
| 301 | + | ||
| 302 | + | #### FreshRSS API |
|
| 303 | + | ||
| 304 | + | If neither of the above are provided the app will default to using a FreshRSS API instance. Set the following environment variables: |
|
| 305 | + | ||
| 306 | + | ``` |
|
| 307 | + | FRESHRSS_URL= |
|
| 308 | + | FRESHRSS_USERNAME= |
|
| 309 | + | FRESHRSS_PASSWORD= |
|
| 310 | + | ``` |
|
| 311 | + | ||
| 312 | + | #### Admin Panel |
|
| 313 | + | ||
| 314 | + | Feeds includes a password-protected admin panel at `/admin` for managing your FreshRSS subscriptions. Set the `ADMIN_PASSWORD` environment variable to enable it. From the admin panel you can view your current subscriptions and add new feeds directly to your FreshRSS instance. |
|
| 315 | + | ||
| 316 | + | #### Feeds API |
|
| 317 | + | ||
| 318 | + | The `/feeds` endpoint exports your FreshRSS subscriptions in JSON or OPML format: |
|
| 319 | + | ||
| 320 | + | ``` |
|
| 321 | + | /feeds?format=json |
|
| 322 | + | /feeds?format=opml |
|
| 323 | + | ``` |
|
| 324 | + | ||
| 325 | + | ### Structure |
|
| 326 | + | ||
| 327 | + | ``` |
|
| 328 | + | feeds/ |
|
| 329 | + | ├── src/ |
|
| 330 | + | │ ├── main.rs # Axum server with routing, templates, and static asset serving |
|
| 331 | + | │ ├── feeds.rs # Feed fetching, OPML parsing, and FreshRSS API integration |
|
| 332 | + | │ ├── auth.rs # Session-based authentication with constant-time password verification |
|
| 333 | + | │ └── models.rs # Data structures for feeds and FreshRSS responses |
|
| 334 | + | ├── templates/ # Askama HTML templates |
|
| 335 | + | ├── assets/ # Static assets embedded at compile time via rust-embed |
|
| 336 | + | ├── Dockerfile |
|
| 337 | + | └── docker-compose.yml |
|
| 338 | + | ``` |
|
| 339 | + | ||
| 340 | + | ### Deployment |
|
| 341 | + | ||
| 342 | + | #### Railway |
|
| 343 | + | ||
| 344 | + | [](https://railway.com/deploy/Ezvmhx?referralCode=JGcIp6) |
|
| 345 | + | ||
| 346 | + | #### Docker |
|
| 347 | + | ||
| 348 | + | ```bash |
|
| 349 | + | cd apps/feeds |
|
| 350 | + | cp .env.sample .env |
|
| 351 | + | # Edit .env with your credentials |
|
| 352 | + | docker compose up -d |
|
| 353 | + | ``` |
|
| 354 | + | ||
| 355 | + | #### Binary |
|
| 356 | + | ||
| 357 | + | ```bash |
|
| 358 | + | cargo build --release -p feeds |
|
| 359 | + | ``` |
|
| 360 | + | ||
| 361 | + | The resulting binary is self-contained with all assets embedded. Copy it to your server with a configured `.env` file and run it directly. |
|
| 362 | + | ||
| 363 | + | ||
| 364 | + | ## Jotts |
|
| 365 | + | ||
| 366 | + | A minimal notes app |
|
| 367 | + | ||
| 368 | + | ### Overview |
|
| 369 | + | ||
| 370 | + | A simple, self-hosted markdown note app built with Rust. |
|
| 371 | + | ||
| 372 | + | * Single \~7MB Rust binary with embedded assets |
|
| 373 | + | * Password authentication with session cookies |
|
| 374 | + | * Create, edit, and delete markdown notes |
|
| 375 | + | * Markdown rendering with strikethrough, tables, and task lists |
|
| 376 | + | * Dark themed UI with Commit Mono font |
|
| 377 | + | * SQLite for persistent storage |
|
| 378 | + | ||
| 379 | + | ### Quickstart |
|
| 380 | + | ||
| 381 | + | ```bash |
|
| 382 | + | git clone https://github.com/stevedylandev/andromeda.git |
|
| 383 | + | cd andromeda |
|
| 384 | + | cp apps/jotts/.env.example .env |
|
| 385 | + | # Edit .env with your password |
|
| 386 | + | cargo run -p jotts |
|
| 387 | + | ``` |
|
| 388 | + | ||
| 389 | + | #### Environment Variables |
|
| 390 | + | ||
| 391 | + | | Variable | Description | Default | |
|
| 392 | + | | ---------------- | --------------------------------- | -------------- | |
|
| 393 | + | | `JOTTS_PASSWORD` | Password for login authentication | `changeme` | |
|
| 394 | + | | `JOTTS_DB_PATH` | SQLite database file path | `jotts.sqlite` | |
|
| 395 | + | | `HOST` | Server bind address | `127.0.0.1` | |
|
| 396 | + | | `PORT` | Server port | `3000` | |
|
| 397 | + | | `COOKIE_SECURE` | Enable HTTPS-only cookies | `false` | |
|
| 398 | + | ||
| 399 | + | ### Structure |
|
| 400 | + | ||
| 401 | + | ``` |
|
| 402 | + | jotts/ |
|
| 403 | + | ├── src/ |
|
| 404 | + | │ ├── main.rs # App entrypoint, env vars, starts server |
|
| 405 | + | │ ├── server.rs # Axum router, HTTP handlers, and templates |
|
| 406 | + | │ ├── auth.rs # Password verification and session management |
|
| 407 | + | │ └── db.rs # SQLite database layer (notes, sessions) |
|
| 408 | + | ├── templates/ # Askama HTML templates |
|
| 409 | + | │ ├── base.html # Base layout with header and nav |
|
| 410 | + | │ ├── login.html # Login page |
|
| 411 | + | │ ├── index.html # Note list |
|
| 412 | + | │ ├── view.html # Single note display |
|
| 413 | + | │ ├── new.html # Create note form |
|
| 414 | + | │ └── edit.html # Edit note form |
|
| 415 | + | ├── static/ # Favicons, og:image, styles, and webmanifest |
|
| 416 | + | ├── assets/ # Commit Mono font files |
|
| 417 | + | ├── Dockerfile |
|
| 418 | + | └── docker-compose.yml |
|
| 419 | + | ``` |
|
| 420 | + | ||
| 421 | + | ### Deployment |
|
| 422 | + | ||
| 423 | + | #### Railway |
|
| 424 | + | ||
| 425 | + | [](https://railway.com/deploy/DLhUhH?referralCode=JGcIp6) |
|
| 426 | + | ||
| 427 | + | #### Docker |
|
| 428 | + | ||
| 429 | + | ```bash |
|
| 430 | + | cd apps/jotts |
|
| 431 | + | cp .env.example .env |
|
| 432 | + | # Edit .env with your password |
|
| 433 | + | docker compose up -d |
|
| 434 | + | ``` |
|
| 435 | + | ||
| 436 | + | This will start Jotts on port `3000` with a persistent volume for the SQLite database. |
|
| 437 | + | ||
| 438 | + | #### Binary |
|
| 439 | + | ||
| 440 | + | ```bash |
|
| 441 | + | cargo build --release -p jotts |
|
| 442 | + | ``` |
|
| 443 | + | ||
| 444 | + | The resulting binary is self-contained with all assets embedded. Copy it to your server with a configured `.env` file and run it directly. |
|
| 445 | + | ||
| 446 | + | ||
| 447 | + | ## OG |
|
| 448 | + | ||
| 449 | + | A simple web tool for inspecting Open Graph tags on any URL. |
|
| 450 | + | ||
| 451 | + | ### Overview |
|
| 452 | + | ||
| 453 | + | A self-hosted Open Graph tag inspector built with Rust. Enter any URL and instantly see its OG metadata. |
|
| 454 | + | ||
| 455 | + | * Single Rust binary with embedded assets |
|
| 456 | + | * Inspects title, description, image, and other OG tags |
|
| 457 | + | * Dark themed UI with Commit Mono font |
|
| 458 | + | * No database needed -- fully stateless |
|
| 459 | + | ||
| 460 | + | ### Quickstart |
|
| 461 | + | ||
| 462 | + | ```bash |
|
| 463 | + | git clone https://github.com/stevedylandev/andromeda.git |
|
| 464 | + | cd andromeda |
|
| 465 | + | cargo run -p og |
|
| 466 | + | ``` |
|
| 467 | + | ||
| 468 | + | #### Environment Variables |
|
| 469 | + | ||
| 470 | + | | Variable | Description | Default | |
|
| 471 | + | | -------- | ----------- | ------- | |
|
| 472 | + | | `PORT` | Server port | `3000` | |
|
| 473 | + | ||
| 474 | + | ### Structure |
|
| 475 | + | ||
| 476 | + | ``` |
|
| 477 | + | og/ |
|
| 478 | + | ├── src/ |
|
| 479 | + | │ ├── main.rs # Entry point and server startup |
|
| 480 | + | │ ├── server.rs # Axum routes and request handling |
|
| 481 | + | │ └── og.rs # Open Graph tag fetching and parsing |
|
| 482 | + | ├── templates/ # Askama HTML templates |
|
| 483 | + | │ ├── base.html # Base layout |
|
| 484 | + | │ ├── index.html # Search form |
|
| 485 | + | │ └── results.html # OG tag results display |
|
| 486 | + | ├── static/ # Fonts, favicons, and styles |
|
| 487 | + | ├── Dockerfile |
|
| 488 | + | └── docker-compose.yml |
|
| 489 | + | ``` |
|
| 490 | + | ||
| 491 | + | ### Deployment |
|
| 492 | + | ||
| 493 | + | #### Railway |
|
| 494 | + | ||
| 495 | + | [](https://railway.com/deploy/OdXBt_?referralCode=JGcIp6) |
|
| 496 | + | ||
| 497 | + | #### Docker |
|
| 498 | + | ||
| 499 | + | ```bash |
|
| 500 | + | cd apps/og |
|
| 501 | + | docker compose up -d |
|
| 502 | + | ``` |
|
| 503 | + | ||
| 504 | + | #### Binary |
|
| 505 | + | ||
| 506 | + | ```bash |
|
| 507 | + | cargo build --release -p og |
|
| 508 | + | ``` |
|
| 509 | + | ||
| 510 | + | The resulting binary is self-contained with all assets embedded. Copy it to your server and run it directly. |
|
| 511 | + | ||
| 512 | + | ||
| 513 | + | ## Parcels |
|
| 514 | + | ||
| 515 | + | A minimal package tracking app |
|
| 516 | + | ||
| 517 | + | :::warning |
|
| 518 | + | This app originally used USPS, but starting April 1st 2026, it has become much harder to obtain/maintain API keys. |
|
| 519 | + | ::: |
|
| 520 | + | ||
| 521 | + | ### Overview |
|
| 522 | + | ||
| 523 | + | A self-hosted package tracker for USPS. Track your packages without logging into USPS every time. |
|
| 524 | + | ||
| 525 | + | * Single \~7MB Rust binary |
|
| 526 | + | * Averages around \~10MB of RAM usage |
|
| 527 | + | * Password authentication |
|
| 528 | + | * Track USPS packages with custom labels |
|
| 529 | + | * Delete packages you no longer want to track |
|
| 530 | + | ||
| 531 | + | ### Quickstart |
|
| 532 | + | ||
| 533 | + | ```bash |
|
| 534 | + | git clone https://github.com/stevedylandev/andromeda.git |
|
| 535 | + | cd andromeda |
|
| 536 | + | cp apps/parcels/.env.example .env |
|
| 537 | + | # Edit .env with your USPS API credentials and app password |
|
| 538 | + | cargo run -p parcels |
|
| 539 | + | ``` |
|
| 540 | + | ||
| 541 | + | You'll need a [USPS Web Tools API](https://developer.usps.com) account to get your `USPS_CLIENT_ID` and `USPS_CLIENT_SECRET`. |
|
| 542 | + | ||
| 543 | + | #### Environment Variables |
|
| 544 | + | ||
| 545 | + | | Variable | Description | Default | |
|
| 546 | + | | -------------------- | --------------------------------- | ------------ | |
|
| 547 | + | | `APP_PASSWORD` | Password for login authentication | *required* | |
|
| 548 | + | | `PARCELS_DB_PATH` | SQLite database file path | `parcels.db` | |
|
| 549 | + | | `USPS_CLIENT_ID` | USPS OAuth2 client ID | *required* | |
|
| 550 | + | | `USPS_CLIENT_SECRET` | USPS OAuth2 client secret | *required* | |
|
| 551 | + | | `PORT` | Server port | `3000` | |
|
| 552 | + | | `COOKIE_SECURE` | Enable HTTPS-only cookies | `false` | |
|
| 553 | + | ||
| 554 | + | ### Structure |
|
| 555 | + | ||
| 556 | + | ``` |
|
| 557 | + | parcels/ |
|
| 558 | + | ├── src/ |
|
| 559 | + | │ ├── main.rs # Axum web server, routes, and app state |
|
| 560 | + | │ ├── auth.rs # Password verification and session management |
|
| 561 | + | │ ├── db.rs # SQLite database layer (packages, events, sessions) |
|
| 562 | + | │ └── usps.rs # USPS API integration with OAuth2 token caching |
|
| 563 | + | ├── templates/ # Askama HTML templates |
|
| 564 | + | │ ├── base.html # Base layout |
|
| 565 | + | │ ├── index.html # Package list |
|
| 566 | + | │ ├── detail.html # Package detail with tracking events |
|
| 567 | + | │ ├── add.html # Add package form |
|
| 568 | + | │ └── login.html # Login page |
|
| 569 | + | ├── static/ # Fonts, favicons, and images |
|
| 570 | + | ├── Dockerfile |
|
| 571 | + | └── docker-compose.yml |
|
| 572 | + | ``` |
|
| 573 | + | ||
| 574 | + | ### Deployment |
|
| 575 | + | ||
| 576 | + | #### Railway |
|
| 577 | + | ||
| 578 | + | [](https://railway.com/deploy/HNQUs4?referralCode=JGcIp6) |
|
| 579 | + | ||
| 580 | + | #### Docker |
|
| 581 | + | ||
| 582 | + | ```bash |
|
| 583 | + | cd apps/parcels |
|
| 584 | + | cp .env.example .env |
|
| 585 | + | # Edit .env with your credentials |
|
| 586 | + | docker compose up -d |
|
| 587 | + | ``` |
|
| 588 | + | ||
| 589 | + | This will start Parcels on port `3000` with a persistent volume for the SQLite database. |
|
| 590 | + | ||
| 591 | + | #### Binary |
|
| 592 | + | ||
| 593 | + | ```bash |
|
| 594 | + | cargo build --release -p parcels |
|
| 595 | + | ``` |
|
| 596 | + | ||
| 597 | + | The resulting binary is self-contained (\~7MB). Copy it to your server with a configured `.env` file and run it directly. |
|
| 598 | + | ||
| 599 | + | ||
| 600 | + | ## Shrink |
|
| 601 | + | ||
| 602 | + | A minimal image compression app |
|
| 603 | + | ||
| 604 | + | ### Overview |
|
| 605 | + | ||
| 606 | + | A simple self-hosted tool for compressing and resizing images. Upload an image, set your desired quality and optional width, and download the compressed JPEG. |
|
| 607 | + | ||
| 608 | + | * Single Rust binary |
|
| 609 | + | * Compress images to JPEG with configurable quality (1-100) |
|
| 610 | + | * Optional resize by width (preserves aspect ratio) |
|
| 611 | + | * 20MB upload limit |
|
| 612 | + | ||
| 613 | + | ### Quickstart |
|
| 614 | + | ||
| 615 | + | ```bash |
|
| 616 | + | git clone https://github.com/stevedylandev/andromeda.git |
|
| 617 | + | cd andromeda |
|
| 618 | + | cargo run -p shrink |
|
| 619 | + | ``` |
|
| 620 | + | ||
| 621 | + | #### Environment Variables |
|
| 622 | + | ||
| 623 | + | | Variable | Description | Default | |
|
| 624 | + | | -------- | ---------------- | ----------- | |
|
| 625 | + | | `HOST` | Server bind host | `127.0.0.1` | |
|
| 626 | + | | `PORT` | Server bind port | `3000` | |
|
| 627 | + | ||
| 628 | + | ### Structure |
|
| 629 | + | ||
| 630 | + | ``` |
|
| 631 | + | shrink/ |
|
| 632 | + | ├── src/ |
|
| 633 | + | │ ├── main.rs # Entry point and server startup |
|
| 634 | + | │ └── server.rs # Axum routes and image compression logic |
|
| 635 | + | ├── templates/ |
|
| 636 | + | │ └── index.html # Upload UI |
|
| 637 | + | ├── static/ # Fonts and static assets |
|
| 638 | + | ├── Dockerfile |
|
| 639 | + | └── docker-compose.yml |
|
| 640 | + | ``` |
|
| 641 | + | ||
| 642 | + | ### Deployment |
|
| 643 | + | ||
| 644 | + | #### Railway |
|
| 645 | + | ||
| 646 | + | [](https://railway.com/deploy/enYUFb?referralCode=JGcIp6) |
|
| 647 | + | ||
| 648 | + | #### Docker |
|
| 649 | + | ||
| 650 | + | ```bash |
|
| 651 | + | cd apps/shrink |
|
| 652 | + | docker compose up -d |
|
| 653 | + | ``` |
|
| 654 | + | ||
| 655 | + | This will start Shrink on port `3000`. |
|
| 656 | + | ||
| 657 | + | #### Binary |
|
| 658 | + | ||
| 659 | + | ```bash |
|
| 660 | + | cargo build --release -p shrink |
|
| 661 | + | ``` |
|
| 662 | + | ||
| 663 | + | The resulting binary is self-contained. Copy it to your server and run it directly. |
|
| 664 | + | ||
| 665 | + | ||
| 666 | + | ## Sipp |
|
| 667 | + | ||
| 668 | + | Minimal code sharing |
|
| 669 | + | ||
| 670 | + | ### Overview |
|
| 671 | + | ||
| 672 | + | A single binary for code sharing with a web server and interactive TUI. |
|
| 673 | + | ||
| 674 | + | * Create snippets and share on the web |
|
| 675 | + | * Raw output for CLI tools -- `curl`, `wget`, and `httpie` get plain text automatically |
|
| 676 | + | * Interactive TUI with authenticated access for snippet management |
|
| 677 | + | * Minimal, fast, and low memory consumption |
|
| 678 | + | ||
| 679 | + | :::warning |
|
| 680 | + | A small demo instance runs at [sipp.so](https://sipp.so). All snippets created there are public and might be deleted at any time; host your own instance with your own API key for personal use! |
|
| 681 | + | ::: |
|
| 682 | + | ||
| 683 | + | ### Quickstart |
|
| 684 | + | ||
| 685 | + | ```bash |
|
| 686 | + | cargo install sipp-so |
|
| 687 | + | sipp --help |
|
| 688 | + | ``` |
|
| 689 | + | ||
| 690 | + | Start a server and create a snippet: |
|
| 691 | + | ||
| 692 | + | ```bash |
|
| 693 | + | sipp server --port 3000 |
|
| 694 | + | ``` |
|
| 695 | + | ||
| 696 | + | ```bash |
|
| 697 | + | # Path to file |
|
| 698 | + | sipp path/to/file.rs |
|
| 699 | + | ||
| 700 | + | # Or use the interactive TUI |
|
| 701 | + | sipp |
|
| 702 | + | ``` |
|
| 703 | + | ||
| 704 | + | #### Install |
|
| 705 | + | ||
| 706 | + | Sipp can be installed several ways: |
|
| 707 | + | ||
| 708 | + | ##### Homebrew |
|
| 709 | + | ||
| 710 | + | ```bash |
|
| 711 | + | brew install stevedylandev/tap/sipp-so |
|
| 712 | + | ``` |
|
| 713 | + | ||
| 714 | + | ##### Cargo |
|
| 715 | + | ||
| 716 | + | ```bash |
|
| 717 | + | cargo install sipp-so |
|
| 718 | + | ``` |
|
| 719 | + | ||
| 720 | + | ##### Releases |
|
| 721 | + | ||
| 722 | + | Visit the [releases](https://github.com/stevedylandev/sipp/releases) page for binaries and install scripts. |
|
| 723 | + | ||
| 724 | + | ### CLI |
|
| 725 | + | ||
| 726 | + | ``` |
|
| 727 | + | sipp [OPTIONS] [FILE] [COMMAND] |
|
| 728 | + | ``` |
|
| 729 | + | ||
| 730 | + | #### Commands |
|
| 731 | + | ||
| 732 | + | | Command | Description | |
|
| 733 | + | | -------- | ------------------------------------------ | |
|
| 734 | + | | `server` | Start the web server | |
|
| 735 | + | | `tui` | Launch the interactive TUI | |
|
| 736 | + | | `auth` | Save remote URL and API key to config file | |
|
| 737 | + | ||
| 738 | + | #### Arguments |
|
| 739 | + | ||
| 740 | + | | Argument | Description | |
|
| 741 | + | | -------- | ---------------------------------- | |
|
| 742 | + | | `[FILE]` | File path to create a snippet from | |
|
| 743 | + | ||
| 744 | + | #### Options |
|
| 745 | + | ||
| 746 | + | | Option | Description | |
|
| 747 | + | | --------------------- | ---------------------------------------------------------- | |
|
| 748 | + | | `-r, --remote <URL>` | Remote server URL (env: `SIPP_REMOTE_URL`) | |
|
| 749 | + | | `-k, --api-key <KEY>` | API key for authenticated operations (env: `SIPP_API_KEY`) | |
|
| 750 | + | ||
| 751 | + | ### Server |
|
| 752 | + | ||
| 753 | + | Sipp includes a built-in web server powered by Axum. Start it with: |
|
| 754 | + | ||
| 755 | + | ```bash |
|
| 756 | + | sipp server --port 3000 --host localhost |
|
| 757 | + | ``` |
|
| 758 | + | ||
| 759 | + | #### Environment Variables |
|
| 760 | + | ||
| 761 | + | | Variable | Description | |
|
| 762 | + | | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | |
|
| 763 | + | | `SIPP_API_KEY` | API key for protecting endpoints | |
|
| 764 | + | | `SIPP_AUTH_ENDPOINTS` | Comma-separated list of endpoints requiring auth: `api_list`, `api_create`, `api_get`, `api_delete`, `all`, or `none` (defaults to `api_delete,api_list`) | |
|
| 765 | + | | `SIPP_MAX_CONTENT_SIZE` | Maximum snippet content size in bytes (defaults to `512000` / 500 KB) | |
|
| 766 | + | | `SIPP_DB_PATH` | Custom path for the SQLite database file (defaults to `sipp.sqlite`) | |
|
| 767 | + | ||
| 768 | + | #### API Endpoints |
|
| 769 | + | ||
| 770 | + | | Method | Endpoint | Description | |
|
| 771 | + | | -------- | -------------------------- | ------------------------------------------------------ | |
|
| 772 | + | | `GET` | `/api/snippets` | List all snippets | |
|
| 773 | + | | `POST` | `/api/snippets` | Create a snippet (`{"name": "...", "content": "..."}`) | |
|
| 774 | + | | `GET` | `/api/snippets/{short_id}` | Get a snippet by ID | |
|
| 775 | + | | `PUT` | `/api/snippets/{short_id}` | Update a snippet | |
|
| 776 | + | | `DELETE` | `/api/snippets/{short_id}` | Delete a snippet by ID | |
|
| 777 | + | ||
| 778 | + | Authenticated endpoints require an `x-api-key` header. |
|
| 779 | + | ||
| 780 | + | #### Raw Output for CLI Tools |
|
| 781 | + | ||
| 782 | + | When you access a snippet URL (`/s/{short_id}`) with `curl`, `wget`, or `httpie`, the server returns the raw content as plain text instead of HTML: |
|
| 783 | + | ||
| 784 | + | ```bash |
|
| 785 | + | curl https://sipp.so/s/abc123 |
|
| 786 | + | ``` |
|
| 787 | + | ||
| 788 | + | ### TUI |
|
| 789 | + | ||
| 790 | + | The Sipp TUI makes it easy to create, copy, share, and manage your snippets either locally or remotely. |
|
| 791 | + | ||
| 792 | + | ```bash |
|
| 793 | + | # Launch TUI (default behavior when no file argument is given) |
|
| 794 | + | sipp |
|
| 795 | + | ||
| 796 | + | # Or explicitly |
|
| 797 | + | sipp tui |
|
| 798 | + | ||
| 799 | + | # With remote options |
|
| 800 | + | sipp -r https://sipp.so -k your-api-key |
|
| 801 | + | ``` |
|
| 802 | + | ||
| 803 | + | #### Local Access |
|
| 804 | + | ||
| 805 | + | If you are running `sipp` in the same directory as the `sipp.sqlite` file created by the server instance, the TUI will automatically access the database locally. |
|
| 806 | + | ||
| 807 | + | #### Remote Access |
|
| 808 | + | ||
| 809 | + | To access a remote instance: |
|
| 810 | + | ||
| 811 | + | * Set the `SIPP_API_KEY` variable in your server instance |
|
| 812 | + | * Run `sipp auth` to enter your server URL and API key, stored under `$HOME/.config/sipp` |
|
| 813 | + | ||
| 814 | + | #### Keybindings |
|
| 815 | + | ||
| 816 | + | | Key | Action | |
|
| 817 | + | | ---------- | ------------------------------ | |
|
| 818 | + | | `j`/`Down` | Move down / Scroll down | |
|
| 819 | + | | `k`/`Up` | Move up / Scroll up | |
|
| 820 | + | | `Enter` | Focus content pane | |
|
| 821 | + | | `Esc` | Back / Quit | |
|
| 822 | + | | `y` | Copy snippet content | |
|
| 823 | + | | `Y` | Copy snippet link | |
|
| 824 | + | | `o` | Open in browser | |
|
| 825 | + | | `e` | Edit snippet | |
|
| 826 | + | | `d` | Delete snippet | |
|
| 827 | + | | `c` | Create snippet | |
|
| 828 | + | | `/` | Search snippets | |
|
| 829 | + | | `r` | Refresh snippets (remote only) | |
|
| 830 | + | | `q` | Quit | |
|
| 831 | + | | `?` | Toggle help | |
|
| 832 | + | ||
| 833 | + | ### Structure |
|
| 834 | + | ||
| 835 | + | ``` |
|
| 836 | + | sipp/ |
|
| 837 | + | ├── src/ |
|
| 838 | + | │ ├── main.rs # CLI argument parsing and entry point |
|
| 839 | + | │ ├── lib.rs # Library exports |
|
| 840 | + | │ ├── server.rs # Axum web server, routes, and templates |
|
| 841 | + | │ ├── tui.rs # Interactive terminal UI |
|
| 842 | + | │ ├── db.rs # SQLite database layer |
|
| 843 | + | │ ├── backend.rs # Local/remote backend abstraction |
|
| 844 | + | │ ├── config.rs # Config file management |
|
| 845 | + | │ └── highlight.rs # Syntax highlighting with custom themes |
|
| 846 | + | ├── templates/ # Askama HTML templates |
|
| 847 | + | ├── static/ # Fonts, favicons, and styles |
|
| 848 | + | ├── Dockerfile |
|
| 849 | + | └── docker-compose.yml |
|
| 850 | + | ``` |
|
| 851 | + | ||
| 852 | + | ### Deployment |
|
| 853 | + | ||
| 854 | + | #### Railway |
|
| 855 | + | ||
| 856 | + | [](https://railway.com/deploy/Axcf_D?referralCode=JGcIp6) |
|
| 857 | + | ||
| 858 | + | #### Docker |
|
| 859 | + | ||
| 860 | + | ```bash |
|
| 861 | + | SIPP_API_KEY=your-secret-key docker compose up -d |
|
| 862 | + | ``` |
|
| 863 | + | ||
| 864 | + | #### Binary |
|
| 865 | + | ||
| 866 | + | ```bash |
|
| 867 | + | cargo build --release -p sipp |
|
| 868 | + | ``` |
|
| 869 | + | ||
| 870 | + | The resulting binary is self-contained with all assets embedded. Copy it to your server with your environment variables configured and run it directly. |
|
| 871 | + |
| 1 | + | # Andromeda |
|
| 2 | + | ||
| 3 | + | ## Docs |
|
| 4 | + | ||
| 5 | + | - [Quickstart](/quickstart): Get up and running with any Andromeda app in minutes. |
|
| 6 | + | - [What is Andromeda](/what-is-andromeda): Andromeda is a Rust workspace of minimal, self-hosted web apps. Each app compiles to a single binary powered by [Axum](https://github.com/tokio-rs/axum), [SQLite](https://github.com/rusqlite/rusqlite), and [Askama](https://github.com/djc/askama) templates. |
|
| 7 | + | - [Skills](/diy/skills): Andromeda apps are scaffolded using [Claude Code](https://claude.ai/code) with a custom skill called `rust-crud`. This page explains how to use it to build your own apps in the same style. |
|
| 8 | + | - [Stack](/diy/stack): Every app in Andromeda is built on the same Rust stack. This page covers the core dependencies and how they fit together. |
|
| 9 | + | - [Feeds](/apps/feeds): Minimal RSS Feeds |
|
| 10 | + | - [Jotts](/apps/jotts): A minimal notes app |
|
| 11 | + | - [OG](/apps/og): A simple web tool for inspecting Open Graph tags on any URL. |
|
| 12 | + | - [Parcels](/apps/parcels): A minimal package tracking app |
|
| 13 | + | - [Shrink](/apps/shrink): A minimal image compression app |
|
| 14 | + | - [Sipp](/apps/sipp): Minimal code sharing |
| 1 | + | <!doctype html> |
|
| 2 | + | <html lang="en" class="dark" data-vocs> |
|
| 3 | + | <head> |
|
| 4 | + | <meta charset="UTF-8" /> |
|
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
| 6 | + | <script src="/initializeTheme.iife.js"></script><title>Quickstart – Andromeda</title><meta property="og:type" content="website"/><meta property="og:title" content="Quickstart"/><meta name="twitter:card" content="summary_large_image"/> |
|
| 7 | + | <script type="module" crossorigin src="/assets/index-DO6OtFZH.js"></script> |
|
| 8 | + | <link rel="stylesheet" crossorigin href="/assets/style-Dg8GuVX0.css"> |
|
| 9 | + | </head> |
|
| 10 | + | <body> |
|
| 11 | + | <span style="display: none;">Are you an LLM? Read <a href="/llms.txt">llms.txt</a> for a summary of the docs, or <a href="/llms-full.txt">llms-full.txt</a> for the full context.</span> |
|
| 12 | + | <div id="app"><div class="vocs_DocsLayout" data-layout="docs"><a class="vocs_SkipLink vocs_utils_visuallyHidden" href="/quickstart#vocs-content">Skip to content</a><div class="vocs_DocsLayout_gutterLeft"><aside class="vocs_Sidebar vocs_DocsLayout_sidebar"><div><div class="vocs_Sidebar_logoWrapper"><div class="vocs_Sidebar_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div><div class="vocs_Sidebar_divider"></div></div><nav class="vocs_Sidebar_navigation"><div class="vocs_Sidebar_group"><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Intro</div></div><div class="vocs_Sidebar_items"><a data-active="true" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/quickstart" data-discover="true">Quickstart</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/what-is-andromeda" data-discover="true">What is Andromeda</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Apps</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/feeds" data-discover="true">Feeds</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/jotts" data-discover="true">Jotts</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/sipp" data-discover="true">Sipp</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/og" data-discover="true">OG</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/shrink" data-discover="true">Shrink</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/parcels" data-discover="true">Parcels</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">DIY</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/stack" data-discover="true">Stack</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/skills" data-discover="true">Skills</a></div></section></div></nav></div><div class="vocs_Sidebar_footer"><div class="vocs_Sidebar_footerCurtain"></div><div class="vocs_Sidebar_footerContent"></div></div></aside></div><div class="vocs_DocsLayout_gutterTop vocs_DocsLayout_gutterTop_offsetLeftGutter"><div class="vocs_DesktopTopNav"><button class="vocs_DesktopSearch_search" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_4lj_" data-state="closed"><svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-top:2px"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>Search...<div class="vocs_DesktopSearch_searchCommand"><div style="background:currentColor;transform:rotate(45deg);width:1.5px;border-radius:2px;height:100%"></div></div></button><div class="vocs_DesktopTopNav_logoWrapper"><div class="vocs_DesktopTopNav_logo"><a style="align-items:center;display:flex;height:56px;margin-top:4px" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_DesktopTopNav_section"></div><div class="vocs_DesktopTopNav_section"></div></div><div class="vocs_MobileTopNav"><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group"><div class="vocs_MobileTopNav_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_MobileTopNav_group"><nav aria-label="Main" data-orientation="horizontal" dir="ltr" class="vocs_MobileTopNav_navigation vocs_NavigationMenu"><div style="position:relative"><ul data-orientation="horizontal" class="vocs_NavigationMenu_list" dir="ltr"></ul></div></nav><div class="vocs_MobileTopNav_navigation vocs_MobileTopNav_navigation_compact"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_kpj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger vocs_MobileTopNav_navigationItem">Menu<div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group" style="margin-right:-8px"><button class="vocs_MobileSearch_searchButton" type="button" aria-label="Search" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_39j_" data-state="closed"><svg width="21" height="21" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div></div></div></div><div class="vocs_DocsLayout_gutterTopCurtain vocs_DocsLayout_gutterTopCurtain_withSidebar"><div class="vocs_DesktopTopNav_curtain"></div><div class="vocs_MobileTopNav_curtain"><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_qj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger"><div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:13px"><svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 79 48" fill="none"><title>Menu</title><path fill="currentColor" d="M19.528 47.232h40.87c1.952 0 3.515-1.562 3.515-3.564a3.5 3.5 0 0 0-3.516-3.516H19.528a3.501 3.501 0 0 0-3.515 3.516c0 2.002 1.562 3.564 3.515 3.564ZM12.057 27.262h55.81a3.501 3.501 0 0 0 3.516-3.516 3.501 3.501 0 0 0-3.515-3.515h-55.81a3.501 3.501 0 0 0-3.516 3.515 3.501 3.501 0 0 0 3.515 3.516ZM4.391 7.34H75.29c2.002 0 3.515-1.563 3.515-3.516 0-2.002-1.513-3.564-3.515-3.564H4.39C2.438.26.876 1.822.876 3.824A3.501 3.501 0 0 0 4.39 7.34Z"></path></svg></div><div class="vocs_MobileTopNav_menuTitle">Quickstart</div></button></div></div><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_5aj_" data-state="closed" class="vocs_MobileTopNav_outlineTrigger">On this page<div aria-label="On this page" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Right</title><path d="M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div></div><div class="vocs_DocsLayout_gutterRight vocs_DocsLayout_gutterRight_withSidebar"><aside class="vocs_Outline"><div class="vocs_AiCtaDropdown"><a class="vocs_Button_button vocs_AiCtaDropdown_buttonLeft vocs_AiCtaDropdown_button vocs_Button_button" href="https://chatgpt.com?hints=search&q=" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><div style="width:14px;height:14px"><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24"><title>OpenAI</title><path fill="currentColor" d="M22.282 9.821a6 6 0 0 0-.516-4.91a6.05 6.05 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a6 6 0 0 0-3.998 2.9a6.05 6.05 0 0 0 .743 7.097a5.98 5.98 0 0 0 .51 4.911a6.05 6.05 0 0 0 6.515 2.9A6 6 0 0 0 13.26 24a6.06 6.06 0 0 0 5.772-4.206a6 6 0 0 0 3.997-2.9a6.06 6.06 0 0 0-.747-7.073M13.26 22.43a4.48 4.48 0 0 1-2.876-1.04l.141-.081l4.779-2.758a.8.8 0 0 0 .392-.681v-6.737l2.02 1.168a.07.07 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494M3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085l4.783 2.759a.77.77 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646M2.34 7.896a4.5 4.5 0 0 1 2.366-1.973V11.6a.77.77 0 0 0 .388.677l5.815 3.354l-2.02 1.168a.08.08 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855l-5.833-3.387L15.119 7.2a.08.08 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667m2.01-3.023l-.141-.085l-4.774-2.782a.78.78 0 0 0-.785 0L9.409 9.23V6.897a.07.07 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135l-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08L8.704 5.46a.8.8 0 0 0-.393.681zm1.097-2.365l2.602-1.5l2.607 1.5v2.999l-2.597 1.5l-2.607-1.5Z"></path></svg></div>Ask in ChatGPT</a><button class="vocs_Button_button vocs_AiCtaDropdown_buttonRight vocs_AiCtaDropdown_button vocs_Button_button" type="button" id="radix-_R_9n_" aria-haspopup="menu" aria-expanded="false" data-state="closed"><div style="width:14px;height:14px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></aside></div><div id="vocs-content" class="vocs_DocsLayout_content vocs_DocsLayout_content_withSidebar vocs_DocsLayout_content_withTopNav"><article class="vocs_Content"><header class="vocs_Header"><h1 class="vocs_H1 vocs_Heading"><div id="quickstart" class="vocs_Heading_slugTarget"></div>Quickstart<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/quickstart#quickstart" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h1></header> |
|
| 13 | + | <p class="vocs_Paragraph">Get up and running with any Andromeda app in minutes.</p> |
|
| 14 | + | <h2 class="vocs_H2 vocs_Heading"><div id="prerequisites" class="vocs_Heading_slugTarget"></div>Prerequisites<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/quickstart#prerequisites" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 15 | + | <p class="vocs_Paragraph">Make sure <a class="vocs_Anchor" href="https://www.rust-lang.org/tools/install" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)">Rust</a> is installed:</p> |
|
| 16 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">rustc</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> --version</span></span></code></pre></div></div> |
|
| 17 | + | <h2 class="vocs_H2 vocs_Heading"><div id="clone-the-workspace" class="vocs_Heading_slugTarget"></div>Clone the Workspace<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/quickstart#clone-the-workspace" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 18 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">git</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> clone</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> https://github.com/stevedylandev/andromeda.git</span></span> |
|
| 19 | + | <span class="line vocs_Span"><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span">cd</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> andromeda</span></span></code></pre></div></div> |
|
| 20 | + | <h2 class="vocs_H2 vocs_Heading"><div id="build-all-apps" class="vocs_Heading_slugTarget"></div>Build All Apps<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/quickstart#build-all-apps" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 21 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> build</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> --release</span></span></code></pre></div></div> |
|
| 22 | + | <h2 class="vocs_H2 vocs_Heading"><div id="run-a-specific-app" class="vocs_Heading_slugTarget"></div>Run a Specific App<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/quickstart#run-a-specific-app" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 23 | + | <p class="vocs_Paragraph">Each app is a workspace member. Run any of them with <code class="vocs_Code">cargo run -p</code>:</p> |
|
| 24 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> run</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> sipp</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> --</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> server</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> --port</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> 3000</span></span> |
|
| 25 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> run</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> feeds</span></span> |
|
| 26 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> run</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> parcels</span></span> |
|
| 27 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> run</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> jotts</span></span> |
|
| 28 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> run</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> og</span></span> |
|
| 29 | + | <span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cargo</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> run</span><span style="color:#91CBFF;--shiki-dark:#91CBFF" class="vocs_Span"> -p</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> shrink</span></span></code></pre></div></div> |
|
| 30 | + | <p class="vocs_Paragraph">Most apps start on <code class="vocs_Code">http://localhost:3000</code> by default. Check each app's page for specific environment variables and configuration.</p> |
|
| 31 | + | <h2 class="vocs_H2 vocs_Heading"><div id="environment-variables" class="vocs_Heading_slugTarget"></div>Environment Variables<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/quickstart#environment-variables" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 32 | + | <p class="vocs_Paragraph">Most apps use a <code class="vocs_Code">.env</code> file for configuration. Copy the example file and fill in your values:</p> |
|
| 33 | + | <div class="vocs_CodeBlock"><div class="vocs_Pre_wrapper"><pre style="background-color:#0a0c10;--shiki-dark-bg:#0a0c10;color:#f0f3f6;--shiki-dark:#f0f3f6" tabindex="0" class="shiki shiki-themes github-dark-high-contrast github-dark-high-contrast vocs_Pre"><button class="vocs_CopyButton" data-copied="false" type="button"><div aria-label="Copy" class="vocs_Icon" role="img" style="--vocs_Icon_size:18px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Copy</title><path d="M5 2V1H10V2H5ZM4.75 0C4.33579 0 4 0.335786 4 0.75V1H3.5C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H7V13H3.5C3.22386 13 3 12.7761 3 12.5V2.5C3 2.22386 3.22386 2 3.5 2H4V2.25C4 2.66421 4.33579 3 4.75 3H10.25C10.6642 3 11 2.66421 11 2.25V2H11.5C11.7761 2 12 2.22386 12 2.5V7H13V2.5C13 1.67157 12.3284 1 11.5 1H11V0.75C11 0.335786 10.6642 0 10.25 0H4.75ZM9 8.5C9 8.77614 8.77614 9 8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8C8.77614 8 9 8.22386 9 8.5ZM10.5 9C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8C10.2239 8 10 8.22386 10 8.5C10 8.77614 10.2239 9 10.5 9ZM13 8.5C13 8.77614 12.7761 9 12.5 9C12.2239 9 12 8.77614 12 8.5C12 8.22386 12.2239 8 12.5 8C12.7761 8 13 8.22386 13 8.5ZM14.5 9C14.7761 9 15 8.77614 15 8.5C15 8.22386 14.7761 8 14.5 8C14.2239 8 14 8.22386 14 8.5C14 8.77614 14.2239 9 14.5 9ZM15 10.5C15 10.7761 14.7761 11 14.5 11C14.2239 11 14 10.7761 14 10.5C14 10.2239 14.2239 10 14.5 10C14.7761 10 15 10.2239 15 10.5ZM14.5 13C14.7761 13 15 12.7761 15 12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5C14 12.7761 14.2239 13 14.5 13ZM14.5 15C14.7761 15 15 14.7761 15 14.5C15 14.2239 14.7761 14 14.5 14C14.2239 14 14 14.2239 14 14.5C14 14.7761 14.2239 15 14.5 15ZM8.5 11C8.77614 11 9 10.7761 9 10.5C9 10.2239 8.77614 10 8.5 10C8.22386 10 8 10.2239 8 10.5C8 10.7761 8.22386 11 8.5 11ZM9 12.5C9 12.7761 8.77614 13 8.5 13C8.22386 13 8 12.7761 8 12.5C8 12.2239 8.22386 12 8.5 12C8.77614 12 9 12.2239 9 12.5ZM8.5 15C8.77614 15 9 14.7761 9 14.5C9 14.2239 8.77614 14 8.5 14C8.22386 14 8 14.2239 8 14.5C8 14.7761 8.22386 15 8.5 15ZM11 14.5C11 14.7761 10.7761 15 10.5 15C10.2239 15 10 14.7761 10 14.5C10 14.2239 10.2239 14 10.5 14C10.7761 14 11 14.2239 11 14.5ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5C12 14.7761 12.2239 15 12.5 15Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button><code class="vocs_Code"><span class="line vocs_Span"><span style="color:#FFB757;--shiki-dark:#FFB757" class="vocs_Span">cp</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> apps/</span><span style="color:#FF9492;--shiki-dark:#FF9492" class="vocs_Span"><</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">app-nam</span><span style="color:#F0F3F6;--shiki-dark:#F0F3F6" class="vocs_Span">e</span><span style="color:#FF9492;--shiki-dark:#FF9492" class="vocs_Span">></span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span">/.env.example</span><span style="color:#ADDCFF;--shiki-dark:#ADDCFF" class="vocs_Span"> .env</span></span></code></pre></div></div> |
|
| 34 | + | <h2 class="vocs_H2 vocs_Heading"><div id="deployment" class="vocs_Heading_slugTarget"></div>Deployment<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/quickstart#deployment" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 35 | + | <p class="vocs_Paragraph">Every app compiles to a single binary with embedded assets, making deployment straightforward. Each app supports:</p> |
|
| 36 | + | <ul class="vocs_List vocs_List_unordered"> |
|
| 37 | + | <li class="vocs_ListItem"><strong class="vocs_Strong">Railway</strong> - one-click deploy buttons on each app's page</li> |
|
| 38 | + | <li class="vocs_ListItem"><strong class="vocs_Strong">Docker</strong> - <code class="vocs_Code">docker compose up -d</code></li> |
|
| 39 | + | <li class="vocs_ListItem"><strong class="vocs_Strong">Binary</strong> - copy the binary to your server and run it directly</li> |
|
| 40 | + | </ul></article><footer class="vocs_Footer" data-layout="docs"><div class="vocs_Footer_container"></div></footer></div><div data-bottom-observer="true"></div></div></div> |
|
| 41 | + | </body> |
|
| 42 | + | </html> |
| 1 | + | <!doctype html> |
|
| 2 | + | <html lang="en" class="dark" data-vocs> |
|
| 3 | + | <head> |
|
| 4 | + | <meta charset="UTF-8" /> |
|
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
| 6 | + | <script src="/initializeTheme.iife.js"></script><title>What is Andromeda</title><meta property="og:type" content="website"/><meta property="og:title" content="What is Andromeda"/><meta name="twitter:card" content="summary_large_image"/> |
|
| 7 | + | <script type="module" crossorigin src="/assets/index-DO6OtFZH.js"></script> |
|
| 8 | + | <link rel="stylesheet" crossorigin href="/assets/style-Dg8GuVX0.css"> |
|
| 9 | + | </head> |
|
| 10 | + | <body> |
|
| 11 | + | <span style="display: none;">Are you an LLM? Read <a href="/llms.txt">llms.txt</a> for a summary of the docs, or <a href="/llms-full.txt">llms-full.txt</a> for the full context.</span> |
|
| 12 | + | <div id="app"><div class="vocs_DocsLayout" data-layout="docs"><a class="vocs_SkipLink vocs_utils_visuallyHidden" href="/what-is-andromeda#vocs-content">Skip to content</a><div class="vocs_DocsLayout_gutterLeft"><aside class="vocs_Sidebar vocs_DocsLayout_sidebar"><div><div class="vocs_Sidebar_logoWrapper"><div class="vocs_Sidebar_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div><div class="vocs_Sidebar_divider"></div></div><nav class="vocs_Sidebar_navigation"><div class="vocs_Sidebar_group"><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Intro</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/quickstart" data-discover="true">Quickstart</a><a data-active="true" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/what-is-andromeda" data-discover="true">What is Andromeda</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">Apps</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/feeds" data-discover="true">Feeds</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/jotts" data-discover="true">Jotts</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/sipp" data-discover="true">Sipp</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/og" data-discover="true">OG</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/shrink" data-discover="true">Shrink</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/apps/parcels" data-discover="true">Parcels</a></div></section><section class="vocs_Sidebar_section vocs_Sidebar_level"><div class="vocs_Sidebar_sectionHeader"><div class="vocs_Sidebar_sectionTitle">DIY</div></div><div class="vocs_Sidebar_items"><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/stack" data-discover="true">Stack</a><a data-active="false" class="vocs_Sidebar_item vocs_Link vocs_Link_styleless" href="/diy/skills" data-discover="true">Skills</a></div></section></div></nav></div><div class="vocs_Sidebar_footer"><div class="vocs_Sidebar_footerCurtain"></div><div class="vocs_Sidebar_footerContent"></div></div></aside></div><div class="vocs_DocsLayout_gutterTop vocs_DocsLayout_gutterTop_offsetLeftGutter"><div class="vocs_DesktopTopNav"><button class="vocs_DesktopSearch_search" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_4lj_" data-state="closed"><svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-top:2px"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>Search...<div class="vocs_DesktopSearch_searchCommand"><div style="background:currentColor;transform:rotate(45deg);width:1.5px;border-radius:2px;height:100%"></div></div></button><div class="vocs_DesktopTopNav_logoWrapper"><div class="vocs_DesktopTopNav_logo"><a style="align-items:center;display:flex;height:56px;margin-top:4px" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_DesktopTopNav_section"></div><div class="vocs_DesktopTopNav_section"></div></div><div class="vocs_MobileTopNav"><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group"><div class="vocs_MobileTopNav_logo"><a style="align-items:center;display:flex;height:100%" href="/" data-discover="true"><div class="vocs_NavLogo_title">Andromeda</div></a></div></div><div class="vocs_MobileTopNav_group"><nav aria-label="Main" data-orientation="horizontal" dir="ltr" class="vocs_MobileTopNav_navigation vocs_NavigationMenu"><div style="position:relative"><ul data-orientation="horizontal" class="vocs_NavigationMenu_list" dir="ltr"></ul></div></nav><div class="vocs_MobileTopNav_navigation vocs_MobileTopNav_navigation_compact"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_kpj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger vocs_MobileTopNav_navigationItem">Menu<div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div><div class="vocs_MobileTopNav_section"><div class="vocs_MobileTopNav_group" style="margin-right:-8px"><button class="vocs_MobileSearch_searchButton" type="button" aria-label="Search" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_39j_" data-state="closed"><svg width="21" height="21" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div></div></div></div><div class="vocs_DocsLayout_gutterTopCurtain vocs_DocsLayout_gutterTopCurtain_withSidebar"><div class="vocs_DesktopTopNav_curtain"></div><div class="vocs_MobileTopNav_curtain"><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_qj_" data-state="closed" class="vocs_MobileTopNav_menuTrigger"><div aria-label="Menu" class="vocs_Icon" role="img" style="--vocs_Icon_size:13px"><svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 79 48" fill="none"><title>Menu</title><path fill="currentColor" d="M19.528 47.232h40.87c1.952 0 3.515-1.562 3.515-3.564a3.5 3.5 0 0 0-3.516-3.516H19.528a3.501 3.501 0 0 0-3.515 3.516c0 2.002 1.562 3.564 3.515 3.564ZM12.057 27.262h55.81a3.501 3.501 0 0 0 3.516-3.516 3.501 3.501 0 0 0-3.515-3.515h-55.81a3.501 3.501 0 0 0-3.516 3.515 3.501 3.501 0 0 0 3.515 3.516ZM4.391 7.34H75.29c2.002 0 3.515-1.563 3.515-3.516 0-2.002-1.513-3.564-3.515-3.564H4.39C2.438.26.876 1.822.876 3.824A3.501 3.501 0 0 0 4.39 7.34Z"></path></svg></div><div class="vocs_MobileTopNav_menuTitle">What is Andromeda</div></button></div></div><div class="vocs_MobileTopNav_curtainGroup"><div class="vocs_MobileTopNav_curtainItem"><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-_R_5aj_" data-state="closed" class="vocs_MobileTopNav_outlineTrigger">On this page<div aria-label="On this page" class="vocs_Icon" role="img" style="--vocs_Icon_size:16px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Right</title><path d="M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></div></div></div><div class="vocs_DocsLayout_gutterRight vocs_DocsLayout_gutterRight_withSidebar"><aside class="vocs_Outline"><div class="vocs_AiCtaDropdown"><a class="vocs_Button_button vocs_AiCtaDropdown_buttonLeft vocs_AiCtaDropdown_button vocs_Button_button" href="https://chatgpt.com?hints=search&q=" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)"><div style="width:14px;height:14px"><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24"><title>OpenAI</title><path fill="currentColor" d="M22.282 9.821a6 6 0 0 0-.516-4.91a6.05 6.05 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a6 6 0 0 0-3.998 2.9a6.05 6.05 0 0 0 .743 7.097a5.98 5.98 0 0 0 .51 4.911a6.05 6.05 0 0 0 6.515 2.9A6 6 0 0 0 13.26 24a6.06 6.06 0 0 0 5.772-4.206a6 6 0 0 0 3.997-2.9a6.06 6.06 0 0 0-.747-7.073M13.26 22.43a4.48 4.48 0 0 1-2.876-1.04l.141-.081l4.779-2.758a.8.8 0 0 0 .392-.681v-6.737l2.02 1.168a.07.07 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494M3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085l4.783 2.759a.77.77 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646M2.34 7.896a4.5 4.5 0 0 1 2.366-1.973V11.6a.77.77 0 0 0 .388.677l5.815 3.354l-2.02 1.168a.08.08 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855l-5.833-3.387L15.119 7.2a.08.08 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667m2.01-3.023l-.141-.085l-4.774-2.782a.78.78 0 0 0-.785 0L9.409 9.23V6.897a.07.07 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135l-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08L8.704 5.46a.8.8 0 0 0-.393.681zm1.097-2.365l2.602-1.5l2.607 1.5v2.999l-2.597 1.5l-2.607-1.5Z"></path></svg></div>Ask in ChatGPT</a><button class="vocs_Button_button vocs_AiCtaDropdown_buttonRight vocs_AiCtaDropdown_button vocs_Button_button" type="button" id="radix-_R_9n_" aria-haspopup="menu" aria-expanded="false" data-state="closed"><div style="width:14px;height:14px"><svg width="100%" height="100%" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Chevron Down</title><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></div></button></div></aside></div><div id="vocs-content" class="vocs_DocsLayout_content vocs_DocsLayout_content_withSidebar vocs_DocsLayout_content_withTopNav"><article class="vocs_Content"><header class="vocs_Header"><h1 class="vocs_H1 vocs_Heading"><div id="what-is-andromeda" class="vocs_Heading_slugTarget"></div>What is Andromeda<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/what-is-andromeda#what-is-andromeda" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h1></header> |
|
| 13 | + | <p class="vocs_Paragraph">Andromeda is a Rust workspace of minimal, self-hosted web apps. Each app compiles to a single binary powered by <a class="vocs_Anchor" href="https://github.com/tokio-rs/axum" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)">Axum</a>, <a class="vocs_Anchor" href="https://github.com/rusqlite/rusqlite" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)">SQLite</a>, and <a class="vocs_Anchor" href="https://github.com/djc/askama" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)">Askama</a> templates.</p> |
|
| 14 | + | <h2 class="vocs_H2 vocs_Heading"><div id="philosophy" class="vocs_Heading_slugTarget"></div>Philosophy<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/what-is-andromeda#philosophy" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 15 | + | <p class="vocs_Paragraph">Every app in Andromeda follows the same principles:</p> |
|
| 16 | + | <ul class="vocs_List vocs_List_unordered"> |
|
| 17 | + | <li class="vocs_ListItem"><strong class="vocs_Strong">Single binary</strong> - Each app compiles to one small binary (~7MB) with all assets embedded at compile time</li> |
|
| 18 | + | <li class="vocs_ListItem"><strong class="vocs_Strong">Minimal resource usage</strong> - Apps average around ~10MB of RAM</li> |
|
| 19 | + | <li class="vocs_ListItem"><strong class="vocs_Strong">Self-hosted</strong> - You own your data and run it on your own infrastructure</li> |
|
| 20 | + | <li class="vocs_ListItem"><strong class="vocs_Strong">Simple deployment</strong> - One binary, one optional <code class="vocs_Code">.env</code> file, no external dependencies</li> |
|
| 21 | + | <li class="vocs_ListItem"><strong class="vocs_Strong">Consistent stack</strong> - All apps share the same Rust stack so patterns are transferable</li> |
|
| 22 | + | </ul> |
|
| 23 | + | <h2 class="vocs_H2 vocs_Heading"><div id="apps" class="vocs_Heading_slugTarget"></div>Apps<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/what-is-andromeda#apps" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 24 | + | <table class="vocs_Table"><thead><tr class="vocs_TableRow"><th class="vocs_TableHeader">App</th><th class="vocs_TableHeader">Description</th></tr></thead><tbody><tr class="vocs_TableRow"><td class="vocs_TableCell"><a class="vocs_Anchor vocs_Link vocs_Link_accent" href="/apps/sipp" data-discover="true">Sipp</a></td><td class="vocs_TableCell">Code sharing with web UI and TUI</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><a class="vocs_Anchor vocs_Link vocs_Link_accent" href="/apps/feeds" data-discover="true">Feeds</a></td><td class="vocs_TableCell">RSS reader with FreshRSS and OPML support</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><a class="vocs_Anchor vocs_Link vocs_Link_accent" href="/apps/parcels" data-discover="true">Parcels</a></td><td class="vocs_TableCell">Package tracking (USPS)</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><a class="vocs_Anchor vocs_Link vocs_Link_accent" href="/apps/jotts" data-discover="true">Jotts</a></td><td class="vocs_TableCell">Markdown notes</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><a class="vocs_Anchor vocs_Link vocs_Link_accent" href="/apps/og" data-discover="true">OG</a></td><td class="vocs_TableCell">Open Graph tag inspector</td></tr><tr class="vocs_TableRow"><td class="vocs_TableCell"><a class="vocs_Anchor vocs_Link vocs_Link_accent" href="/apps/shrink" data-discover="true">Shrink</a></td><td class="vocs_TableCell">Image compression and resizing</td></tr></tbody></table> |
|
| 25 | + | <h2 class="vocs_H2 vocs_Heading"><div id="shared-crates" class="vocs_Heading_slugTarget"></div>Shared Crates<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/what-is-andromeda#shared-crates" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 26 | + | <table class="vocs_Table"><thead><tr class="vocs_TableRow"><th class="vocs_TableHeader">Crate</th><th class="vocs_TableHeader">Description</th></tr></thead><tbody><tr class="vocs_TableRow"><td class="vocs_TableCell"><code class="vocs_Code">andromeda-auth</code></td><td class="vocs_TableCell">Session-based password authentication</td></tr></tbody></table> |
|
| 27 | + | <p class="vocs_Paragraph">The <code class="vocs_Code">andromeda-auth</code> crate provides a shared authentication layer used across apps that require login, including session cookies and constant-time password verification.</p> |
|
| 28 | + | <h2 class="vocs_H2 vocs_Heading"><div id="license" class="vocs_Heading_slugTarget"></div>License<a class="vocs_Anchor vocs_Autolink" aria-hidden="true" tabindex="-1" href="/what-is-andromeda#license" data-discover="true"><div data-autolink-icon="true" class="vocs_Div vocs_AutolinkIcon" style="--vocs_AutolinkIcon_iconUrl:url(/.vocs/icons/link.svg)"></div></a></h2> |
|
| 29 | + | <p class="vocs_Paragraph"><a class="vocs_Anchor" href="https://github.com/stevedylandev/andromeda/blob/main/LICENSE" target="_blank" rel="noopener noreferrer" style="--vocs_ExternalLink_iconUrl:url(/.vocs/icons/arrow-diagonal.svg)">MIT</a></p></article><footer class="vocs_Footer" data-layout="docs"><div class="vocs_Footer_container"></div></footer></div><div data-bottom-observer="true"></div></div></div> |
|
| 30 | + | </body> |
|
| 31 | + | </html> |
| 1 | 1 | .vocs_DocsLayout_content { |
|
| 2 | - | background: transparent !important; |
|
| 2 | + | background: #121113 !important; |
|
| 3 | 3 | } |
|
| 4 | 4 | ||
| 5 | 5 | .vocs_Content { |
|
| 6 | 6 | height: 100%; |
|
| 7 | + | background: #121113 !important; |
|
| 7 | 8 | } |
| 1 | + | # Posts |
|
| 2 | + | ||
| 3 | + | A minimal CMS blog with admin interface |
|
| 4 | + | ||
| 5 | + | ## Overview |
|
| 6 | + | ||
| 7 | + | A self-hosted blog CMS built with Rust. |
|
| 8 | + | ||
| 9 | + | - Single Rust binary with embedded assets |
|
| 10 | + | - Password authentication with session cookies |
|
| 11 | + | - Create, edit, publish, and delete blog posts with markdown |
|
| 12 | + | - Static pages with custom navigation links |
|
| 13 | + | - File uploads with admin management |
|
| 14 | + | - Custom CSS support from the admin panel |
|
| 15 | + | - RSS feed at `/feed.xml` |
|
| 16 | + | - Dark themed UI with Commit Mono font |
|
| 17 | + | - SQLite for persistent storage |
|
| 18 | + | ||
| 19 | + | ## Quickstart |
|
| 20 | + | ||
| 21 | + | ```bash |
|
| 22 | + | git clone https://github.com/stevedylandev/andromeda.git |
|
| 23 | + | cd andromeda |
|
| 24 | + | cp apps/posts/.env.example .env |
|
| 25 | + | # Edit .env with your password |
|
| 26 | + | cargo run -p posts |
|
| 27 | + | ``` |
|
| 28 | + | ||
| 29 | + | ### Environment Variables |
|
| 30 | + | ||
| 31 | + | | Variable | Description | Default | |
|
| 32 | + | |---|---|---| |
|
| 33 | + | | `POSTS_PASSWORD` | Password for admin login | `changeme` | |
|
| 34 | + | | `POSTS_DB_PATH` | SQLite database file path | `posts.sqlite` | |
|
| 35 | + | | `UPLOADS_DIR` | Directory for uploaded files | `uploads` | |
|
| 36 | + | | `SITE_URL` | Public URL for RSS feed and links | `http://localhost:3000` | |
|
| 37 | + | | `HOST` | Server bind address | `127.0.0.1` | |
|
| 38 | + | | `PORT` | Server port | `3000` | |
|
| 39 | + | | `COOKIE_SECURE` | Enable HTTPS-only cookies | `false` | |
|
| 40 | + | ||
| 41 | + | ## Structure |
|
| 42 | + | ||
| 43 | + | ``` |
|
| 44 | + | posts/ |
|
| 45 | + | ├── src/ |
|
| 46 | + | │ ├── main.rs # App entrypoint, env vars, starts server |
|
| 47 | + | │ ├── server.rs # Axum router, HTTP handlers, and templates |
|
| 48 | + | │ ├── auth.rs # Password verification and session management |
|
| 49 | + | │ └── db.rs # SQLite database layer (posts, pages, files, settings, sessions) |
|
| 50 | + | ├── templates/ # Askama HTML templates |
|
| 51 | + | │ ├── base.html # Public base layout |
|
| 52 | + | │ ├── index.html # Blog home page |
|
| 53 | + | │ ├── post.html # Single post view |
|
| 54 | + | │ ├── posts.html # Post listing |
|
| 55 | + | │ ├── page.html # Static page view |
|
| 56 | + | │ ├── login.html # Login page |
|
| 57 | + | │ ├── admin_base.html # Admin layout |
|
| 58 | + | │ ├── admin_index.html # Admin dashboard |
|
| 59 | + | │ ├── admin_post_form.html # Create/edit post form |
|
| 60 | + | │ ├── admin_pages.html # Admin page listing |
|
| 61 | + | │ ├── admin_page_form.html # Create/edit page form |
|
| 62 | + | │ ├── admin_files.html # File upload management |
|
| 63 | + | │ └── admin_settings.html # Blog settings |
|
| 64 | + | ├── static/ # Favicons, fonts, and styles |
|
| 65 | + | ├── uploads/ # Uploaded files directory |
|
| 66 | + | ├── Dockerfile |
|
| 67 | + | └── docker-compose.yml |
|
| 68 | + | ``` |
|
| 69 | + | ||
| 70 | + | ## Deployment |
|
| 71 | + | ||
| 72 | + | ### Railway |
|
| 73 | + | ||
| 74 | + | [](https://railway.com/deploy/tYtJYp?referralCode=JGcIp6) |
|
| 75 | + | ||
| 76 | + | ### Docker |
|
| 77 | + | ||
| 78 | + | ```bash |
|
| 79 | + | cd apps/posts |
|
| 80 | + | cp .env.example .env |
|
| 81 | + | # Edit .env with your password |
|
| 82 | + | docker compose up -d |
|
| 83 | + | ``` |
|
| 84 | + | ||
| 85 | + | This will start Posts on port `3000` with a persistent volume for the SQLite database and uploads. |
|
| 86 | + | ||
| 87 | + | ### Binary |
|
| 88 | + | ||
| 89 | + | ```bash |
|
| 90 | + | cargo build --release -p posts |
|
| 91 | + | ``` |
|
| 92 | + | ||
| 93 | + | The resulting binary is self-contained with all assets embedded. Copy it to your server with a configured `.env` file and run it directly. |
Binary file — no preview.
Binary file — no preview.
| 1 | 1 | @import "tailwindcss"; |
|
| 2 | 2 | ||
| 3 | + | @font-face { |
|
| 4 | + | font-family: "Commit Mono"; |
|
| 5 | + | src: url("/CommitMono-400-Regular.otf") format("opentype"); |
|
| 6 | + | font-weight: 400; |
|
| 7 | + | font-style: normal; |
|
| 8 | + | } |
|
| 9 | + | ||
| 10 | + | @font-face { |
|
| 11 | + | font-family: "Commit Mono"; |
|
| 12 | + | src: url("/CommitMono-700-Regular.otf") format("opentype"); |
|
| 13 | + | font-weight: 700; |
|
| 14 | + | font-style: normal; |
|
| 15 | + | } |
|
| 16 | + | ||
| 17 | + | * { |
|
| 18 | + | font-family: "Commit Mono", monospace, sans-serif; |
|
| 19 | + | scrollbar-width: none; |
|
| 20 | + | -ms-overflow-style: none; |
|
| 21 | + | } |
|
| 22 | + | ||
| 23 | + | *::-webkit-scrollbar { |
|
| 24 | + | display: none; |
|
| 25 | + | } |
|
| 26 | + | ||
| 27 | + | /* Sidebar section titles */ |
|
| 28 | + | .vocs_Sidebar_sectionTitle { |
|
| 29 | + | text-transform: uppercase; |
|
| 30 | + | opacity: 0.5; |
|
| 31 | + | font-weight: 400; |
|
| 32 | + | font-size: 12px; |
|
| 33 | + | } |
|
| 34 | + | ||
| 35 | + | /* Table headers */ |
|
| 36 | + | th { |
|
| 37 | + | text-transform: uppercase; |
|
| 38 | + | } |
|
| 39 | + | ||
| 40 | + | /* Interactive elements */ |
|
| 41 | + | button, input, textarea, select { |
|
| 42 | + | background: #121113; |
|
| 43 | + | color: #ffffff; |
|
| 44 | + | border: 1px solid white; |
|
| 45 | + | padding: 0.4rem 0.75rem; |
|
| 46 | + | font-size: 14px; |
|
| 47 | + | border-radius: 0; |
|
| 48 | + | } |
|
| 49 | + | ||
| 50 | + | button:hover { |
|
| 51 | + | opacity: 0.7; |
|
| 52 | + | } |
|
| 53 | + | ||
| 54 | + | a:hover { |
|
| 55 | + | opacity: 0.7; |
|
| 56 | + | } |
|
| 57 | + | ||
| 58 | + | /* Homepage logo */ |
|
| 3 | 59 | .vocs_HomePage_logo { |
|
| 4 | 60 | height: auto !important; |
|
| 5 | 61 | width: 100% !important; |
| 12 | 12 | }, |
|
| 13 | 13 | theme: { |
|
| 14 | 14 | colorScheme: "dark", |
|
| 15 | - | accentColor: "#FFB757", |
|
| 15 | + | accentColor: "#ffffff", |
|
| 16 | + | variables: { |
|
| 17 | + | borderRadius: { |
|
| 18 | + | '0': '0px', |
|
| 19 | + | '2': '0px', |
|
| 20 | + | '4': '0px', |
|
| 21 | + | '8': '0px', |
|
| 22 | + | }, |
|
| 23 | + | color: { |
|
| 24 | + | white: { light: '#ffffff', dark: '#ffffff' }, |
|
| 25 | + | black: { light: '#121113', dark: '#121113' }, |
|
| 26 | + | background: { light: '#121113', dark: '#121113' }, |
|
| 27 | + | background2: { light: '#121113', dark: '#121113' }, |
|
| 28 | + | background3: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 29 | + | background4: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 30 | + | background5: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 31 | + | backgroundAccent: { light: '#ffffff', dark: '#ffffff' }, |
|
| 32 | + | backgroundAccentHover: { light: '#ffffff', dark: '#ffffff' }, |
|
| 33 | + | backgroundAccentText: { light: '#121113', dark: '#121113' }, |
|
| 34 | + | backgroundBlueTint: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 35 | + | backgroundDark: { light: '#121113', dark: '#121113' }, |
|
| 36 | + | backgroundGreenTint: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 37 | + | backgroundGreenTint2: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 38 | + | backgroundIrisTint: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 39 | + | backgroundRedTint: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 40 | + | backgroundRedTint2: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 41 | + | backgroundYellowTint: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 42 | + | border: { light: '#333', dark: '#333' }, |
|
| 43 | + | border2: { light: '#555', dark: '#555' }, |
|
| 44 | + | borderAccent: { light: '#ffffff', dark: '#ffffff' }, |
|
| 45 | + | borderBlue: { light: '#555', dark: '#555' }, |
|
| 46 | + | borderGreen: { light: '#555', dark: '#555' }, |
|
| 47 | + | borderIris: { light: '#555', dark: '#555' }, |
|
| 48 | + | borderRed: { light: '#555', dark: '#555' }, |
|
| 49 | + | borderYellow: { light: '#555', dark: '#555' }, |
|
| 50 | + | heading: { light: '#ffffff', dark: '#ffffff' }, |
|
| 51 | + | shadow: { light: 'transparent', dark: 'transparent' }, |
|
| 52 | + | text: { light: '#ffffff', dark: '#ffffff' }, |
|
| 53 | + | text2: { light: 'rgba(255,255,255,0.7)', dark: 'rgba(255,255,255,0.7)' }, |
|
| 54 | + | text3: { light: 'rgba(255,255,255,0.5)', dark: 'rgba(255,255,255,0.5)' }, |
|
| 55 | + | text4: { light: 'rgba(255,255,255,0.3)', dark: 'rgba(255,255,255,0.3)' }, |
|
| 56 | + | textAccent: { light: '#ffffff', dark: '#ffffff' }, |
|
| 57 | + | textAccentHover: { light: 'rgba(255,255,255,0.7)', dark: 'rgba(255,255,255,0.7)' }, |
|
| 58 | + | textBlue: { light: '#ffffff', dark: '#ffffff' }, |
|
| 59 | + | textBlueHover: { light: 'rgba(255,255,255,0.7)', dark: 'rgba(255,255,255,0.7)' }, |
|
| 60 | + | textGreen: { light: '#ffffff', dark: '#ffffff' }, |
|
| 61 | + | textGreenHover: { light: 'rgba(255,255,255,0.7)', dark: 'rgba(255,255,255,0.7)' }, |
|
| 62 | + | textIris: { light: '#ffffff', dark: '#ffffff' }, |
|
| 63 | + | textIrisHover: { light: 'rgba(255,255,255,0.7)', dark: 'rgba(255,255,255,0.7)' }, |
|
| 64 | + | textRed: { light: '#ffffff', dark: '#ffffff' }, |
|
| 65 | + | textRedHover: { light: 'rgba(255,255,255,0.7)', dark: 'rgba(255,255,255,0.7)' }, |
|
| 66 | + | textYellow: { light: '#ffffff', dark: '#ffffff' }, |
|
| 67 | + | textYellowHover: { light: 'rgba(255,255,255,0.7)', dark: 'rgba(255,255,255,0.7)' }, |
|
| 68 | + | ||
| 69 | + | blockquoteBorder: { light: '#555', dark: '#555' }, |
|
| 70 | + | blockquoteText: { light: 'rgba(255,255,255,0.7)', dark: 'rgba(255,255,255,0.7)' }, |
|
| 71 | + | codeBlockBackground: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 72 | + | codeCharacterHighlightBackground: { light: '#333', dark: '#333' }, |
|
| 73 | + | codeHighlightBackground: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 74 | + | codeHighlightBorder: { light: '#333', dark: '#333' }, |
|
| 75 | + | codeInlineBackground: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 76 | + | codeInlineBorder: { light: '#333', dark: '#333' }, |
|
| 77 | + | codeInlineText: { light: '#ffffff', dark: '#ffffff' }, |
|
| 78 | + | codeTitleBackground: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 79 | + | dangerBackground: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 80 | + | dangerBorder: { light: '#ffffff', dark: '#ffffff' }, |
|
| 81 | + | dangerText: { light: 'rgba(255,255,255,0.8)', dark: 'rgba(255,255,255,0.8)' }, |
|
| 82 | + | dangerTextHover: { light: '#ffffff', dark: '#ffffff' }, |
|
| 83 | + | hr: { light: '#333', dark: '#333' }, |
|
| 84 | + | infoBackground: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 85 | + | infoBorder: { light: '#555', dark: '#555' }, |
|
| 86 | + | infoText: { light: 'rgba(255,255,255,0.7)', dark: 'rgba(255,255,255,0.7)' }, |
|
| 87 | + | infoTextHover: { light: '#ffffff', dark: '#ffffff' }, |
|
| 88 | + | lineNumber: { light: 'rgba(255,255,255,0.3)', dark: 'rgba(255,255,255,0.3)' }, |
|
| 89 | + | link: { light: '#ffffff', dark: '#ffffff' }, |
|
| 90 | + | linkHover: { light: 'rgba(255,255,255,0.7)', dark: 'rgba(255,255,255,0.7)' }, |
|
| 91 | + | noteBackground: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 92 | + | noteBorder: { light: '#555', dark: '#555' }, |
|
| 93 | + | noteText: { light: 'rgba(255,255,255,0.7)', dark: 'rgba(255,255,255,0.7)' }, |
|
| 94 | + | successBackground: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 95 | + | successBorder: { light: '#555', dark: '#555' }, |
|
| 96 | + | successText: { light: 'rgba(255,255,255,0.7)', dark: 'rgba(255,255,255,0.7)' }, |
|
| 97 | + | successTextHover: { light: '#ffffff', dark: '#ffffff' }, |
|
| 98 | + | tableBorder: { light: '#333', dark: '#333' }, |
|
| 99 | + | tableHeaderBackground: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 100 | + | tableHeaderText: { light: 'rgba(255,255,255,0.5)', dark: 'rgba(255,255,255,0.5)' }, |
|
| 101 | + | tipBackground: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 102 | + | tipBorder: { light: '#555', dark: '#555' }, |
|
| 103 | + | tipText: { light: 'rgba(255,255,255,0.7)', dark: 'rgba(255,255,255,0.7)' }, |
|
| 104 | + | tipTextHover: { light: '#ffffff', dark: '#ffffff' }, |
|
| 105 | + | warningBackground: { light: '#1e1c1f', dark: '#1e1c1f' }, |
|
| 106 | + | warningBorder: { light: '#555', dark: '#555' }, |
|
| 107 | + | warningText: { light: 'rgba(255,255,255,0.7)', dark: 'rgba(255,255,255,0.7)' }, |
|
| 108 | + | warningTextHover: { light: '#ffffff', dark: '#ffffff' }, |
|
| 109 | + | }, |
|
| 110 | + | content: { |
|
| 111 | + | horizontalPadding: '1rem', |
|
| 112 | + | verticalPadding: '2rem', |
|
| 113 | + | width: '700px', |
|
| 114 | + | }, |
|
| 115 | + | fontFamily: { |
|
| 116 | + | default: '"Commit Mono", monospace, sans-serif', |
|
| 117 | + | mono: '"Commit Mono", monospace', |
|
| 118 | + | }, |
|
| 119 | + | fontSize: { |
|
| 120 | + | root: '14px', |
|
| 121 | + | h1: '18px', |
|
| 122 | + | h2: '16px', |
|
| 123 | + | h3: '15px', |
|
| 124 | + | h4: '14px', |
|
| 125 | + | h5: '14px', |
|
| 126 | + | h6: '14px', |
|
| 127 | + | code: '13px', |
|
| 128 | + | codeBlock: '13px', |
|
| 129 | + | lineNumber: '12px', |
|
| 130 | + | subtitle: '14px', |
|
| 131 | + | th: '12px', |
|
| 132 | + | td: '14px', |
|
| 133 | + | }, |
|
| 134 | + | fontWeight: { |
|
| 135 | + | regular: '400', |
|
| 136 | + | medium: '400', |
|
| 137 | + | semibold: '700', |
|
| 138 | + | }, |
|
| 139 | + | lineHeight: { |
|
| 140 | + | code: '1.6', |
|
| 141 | + | heading: '1.4', |
|
| 142 | + | listItem: '1.6', |
|
| 143 | + | outlineItem: '1.6', |
|
| 144 | + | paragraph: '1.6', |
|
| 145 | + | }, |
|
| 146 | + | }, |
|
| 16 | 147 | }, |
|
| 17 | 148 | sidebar: [ |
|
| 18 | 149 | { |
|
| 54 | 185 | { |
|
| 55 | 186 | text: 'Parcels', |
|
| 56 | 187 | link: '/apps/parcels', |
|
| 188 | + | }, |
|
| 189 | + | { |
|
| 190 | + | text: 'Posts', |
|
| 191 | + | link: '/apps/posts', |
|
| 57 | 192 | }, |
|
| 58 | 193 | ], |
|
| 59 | 194 | }, |
|