feat: home page with URL conversion endpoint

style: mobile optimization
This commit is contained in:
httpjamesm 2022-12-27 23:39:34 -05:00
parent 85dad1cbe0
commit 2ae093b43d
6 changed files with 166 additions and 11 deletions

29
main.go
View File

@ -24,6 +24,35 @@ func main() {
c.String(200, "User-agent: *\nDisallow: /")
})
r.GET("/", func(c *gin.Context) {
c.HTML(200, "home.html", gin.H{})
})
type urlConversionRequest struct {
URL string `form:"url" binding:"required"`
}
r.POST("/", func(c *gin.Context) {
body := urlConversionRequest{}
if err := c.ShouldBind(&body); err != nil {
c.JSON(400, gin.H{"success": false, "message": "Invalid request body"})
return
}
soLink := body.URL
// validate URL
if !strings.HasPrefix(soLink, "https://stackoverflow.com/questions/") {
c.JSON(400, gin.H{"success": false, "message": "Invalid URL"})
return
}
// redirect to the proxied thread
c.Redirect(302, fmt.Sprintf("/questions/%s", strings.TrimPrefix(soLink, "https://stackoverflow.com/questions/")))
})
r.GET("/questions/:id/:title", func(c *gin.Context) {
questionId := c.Param("id")
questionTitle := c.Param("title")

11
public/globals.css Normal file
View File

@ -0,0 +1,11 @@
a {
color: #92adff;
}
html {
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
}

74
public/home.css Normal file
View File

@ -0,0 +1,74 @@
body {
background-color: #1b1f26;
font-family: sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
overflow: hidden;
margin: 0;
color: white;
}
.container {
width: 40rem;
}
.footer {
font-size: 0.8rem;
text-align: center;
}
.view-form {
display: flex;
gap: .5rem;
align-items: center;
}
.view-input {
width: 100%;
padding: .5rem;
border: 2px solid transparent;
border-radius: 3px;
background-color: #2b303b;
color: white;
transition-duration: 200ms;
}
.view-input:focus {
outline: none;
border: 2px solid rgb(168, 168, 168);
}
.view-button {
padding: .5rem;
border: 2px solid transparent;
border-radius: 3px;
background-color: #2b303b;
color: white;
transition-duration: 200ms;
cursor: pointer;
}
.view-button:hover {
background-color: #3b404b;
}
@media screen and (max-width: 800px) {
body {
padding: 1rem;
box-sizing: border-box;
}
}

View File

@ -2,13 +2,6 @@
--code-bg: #36383d;
}
html {
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
}
body {
margin: 0;
width: 100vw;
@ -57,10 +50,6 @@ pre {
font-size: 0.8rem;
}
a {
color: #92adff;
}
.answer-divider {
margin-top: 3rem;
margin-bottom: 3rem;
@ -100,3 +89,10 @@ img {
text-align: right;
font-size: .8rem;
}
@media only screen and (max-width: 800px) {
body {
padding-left: 1rem;
padding-right: 1rem;
}
}

43
templates/home.html Normal file
View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<title>AnonymousOverflow - Private frontend for StackOverflow</title>
<link rel="stylesheet" href="/static/globals.css" />
<link rel="stylesheet" href="/static/home.css" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<div class="container">
<h1>AnonymousOverflow</h1>
<h2>Get programming help without compromising your privacy.</h2>
<p>
AnonymousOverflow allows you to view StackOverflow threads
without the cluttered interface and exposing your IP address,
browsing habits and other browser fingerprint data to
StackOverflow.
</p>
<form method="POST">
<div class="view-form">
<input class="view-input" type="text" name="url" placeholder="https://stackoverflow.com/questions/123456/example-url" />
<button class="view-button" type="submit">View</button>
</div>
</form>
<p class="footer">
Brought to you by
<a
href="https://whatever.social"
target="_blank"
rel="noopener noreferrer"
>Whatever Labs</a
>
<a
href="https://github.com/httpjamesm/AnonymousOverflow"
target="_blank"
rel="noopener noreferrer"
>Source</a
>
</p>
</div>
</body>
</html>

View File

@ -3,6 +3,8 @@
<head>
<title>{{ .title }}</title>
<link rel="stylesheet" href="/static/question.css" />
<link rel="stylesheet" href="/static/globals.css" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; style-src 'self'; script-src 'none'; img-src https:;"