[HN Gopher] Show HN: I created a URL shortener that can be entir...
       ___________________________________________________________________
        
       Show HN: I created a URL shortener that can be entirely hosted on
       GitHub Pages
        
       Author : nelsontky
       Score  : 269 points
       Date   : 2020-11-16 12:35 UTC (8 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | [deleted]
        
       | ROARosen wrote:
       | Not working now...
       | 
       | EDIT (After 1 minute): Looks like its working again. Wonder how
       | such a service can go down. Was Github's server failing or DNS?
        
         | nelsontky wrote:
         | Probably GitHub's API went down for an instance since I didn't
         | make any new pushes then!
        
       | Exuma wrote:
       | If you're using github pages you should just structure jekyll
       | such that you can edit data/_links.yml instead of having
       | thousands of users wasting compute power for github api when its
       | not necessary
        
         | nelsontky wrote:
         | I would suppose doing a push every time a new URL is added
         | would be quite expensive for GitHub too. Plus, GitHUb pages is
         | not updated immediately upon push and it takes some time for
         | new links to work. That being said, this is definitely not the
         | most realistic implementation of a URL shortener. It is meant
         | to be cool and hacky and definitely not used for production!
        
       | futhey wrote:
       | Such a fun little hack. The killer feature is that you found a
       | way for anyone to create a new short URL without a pull request
       | or any changes to the original repository. Nice work.
        
         | nelsontky wrote:
         | Thank you for the kind comments! That's was the aim of the
         | project, to make it fun and easy to create new short links!
        
       | nelsontky wrote:
       | I was always fixated with URL shorteners and always wanted to
       | write one myself. While it would be easy to write one that works
       | with a server, I loved the idea of hosting and running one for
       | free.
       | 
       | Thus, I wrote this URL shortener which does not need a backend to
       | work at all. It uses GitHub issues as a "database", and unlike
       | most other URL shorteners that do not need backends, this one
       | doesn't need a # prefixed to the alias. (i.e. short URLs look
       | clean like this: nlsn.cf/1 instead of looking like this:
       | nlsn.cf/#1)
       | 
       | I haven't had the time to work on it more but do let me know what
       | you guys think! Thank you and hope yall enjoy it!
        
         | rsync wrote:
         | "I was always fixated with URL shorteners and always wanted to
         | write one myself. While it would be easy to write one that
         | works with a server, I loved the idea of hosting and running
         | one for free."
         | 
         | I felt exactly the same way and did, in fact, build one.[1]
         | 
         | It was pretty simple. There's an interesting twist to the
         | particular one I built - it's not specifically a URL shortener,
         | it's a "Universal Shortener".[2] Also no tracking or cookies or
         | third party connections, which I find pleasing.
         | 
         | The disappointing part is seeing the malicious spam and
         | phishing URLs that get shortened. We have had to manually flag-
         | hold-approve a lot of strings and IIRC we outright block
         | anything with 'paypal' in it.
         | 
         | We also gave a kill-function to our upstream ISP so that they
         | could immediately act on phishing complaints without our having
         | to be involved in real-time.
         | 
         | [1] https://0x.co
         | 
         | [2] https://0x.co/hnfaq.html
        
           | ValentineC wrote:
           | Since we're on HN, and this isn't addressed in either FAQ:
           | did anyone end up paying for custom codes?
        
             | rsync wrote:
             | Yes! People do, in fact, buy codes.
             | 
             | I've spent almost zero time on "Oh By" in the last 24
             | months as things at rsync.net have been very busy. So, we
             | haven't made a sale in months due to lack of publicizing
             | it.
             | 
             | However, I think there are unknown, emergent use-cases out
             | there for "Oh By" that I hope people will discover. I am
             | going to pivot back to "Oh By" next year ...
        
           | nelsontky wrote:
           | Oh that is cool! It does remind me of https://telegra.ph/ by
           | Telegram! (Even though they weren't really advertising it as
           | a universal shortener). Just a quick question, how did you
           | promote your platform!
        
             | rsync wrote:
             | I've done almost nothing to promote it. I just mention it
             | once in a while (like now) when the topic of shorteners
             | comes up.
             | 
             | I also sent a notice to all rsync.net customers, years ago,
             | when we launched it.
             | 
             | That's it.
        
         | bdorn wrote:
         | > does not need a backend
         | 
         | GitHub issues infrastructure is a backend!
        
         | diggan wrote:
         | Looks nice and simple! Bit strange to claim "there is no
         | database" and then add "GitHub issues is the database", maybe
         | add "there is no traditional RDMS/document database needed" or
         | something similar.
         | 
         | You might want to detect infinite loops as well :)
         | https://nlsn.cf/6
         | 
         | Last note, the status code seems to be incorrectly set to 404
         | instead of any of the redirection status code. If you're
         | hosting it on GitHub pages, I'm not sure you can actually
         | control it. If the status code was correctly set + the Location
         | header, I think all browsers would be able to detect the
         | infinite loop automatically and prevent it.
        
           | quyleanh wrote:
           | If you use it personally and you know what you are doing, I
           | think this idea is good. For example I have my own domain and
           | when I share long link to friends, I can use it.
           | 
           | By the way, your feedback is good for author improves. Thank
           | you.
        
           | nelsontky wrote:
           | HAHA so that was you. That was a good one! Yes and that title
           | is definitely slightly misleading I kinda didn't want it to
           | get so long and wanted that slight clickbait effect.
           | 
           | Yep I actually cannot control the status code at all. Part of
           | what made this a fun and hacky project was the fact that I
           | was actually redirecting to the actual URLs by catching the
           | 404s. So, the only way i could think of catching the infinite
           | loop was to supply the domain. That being said, I do
           | appreciate the feedback and it's always great to learn more!
        
             | diggan wrote:
             | Indeed :)
             | 
             | I think you could catch the infinitive loop client-side as
             | well by comparing what the URL to redirect to is, and
             | comparing it with the current URL. If they are the same,
             | prevent the redirect. Although you would still be able to
             | create loops by using two issues instead. Maybe just
             | comparing the full hostname? If it's nlsn.cf, don't
             | redirect.
        
             | alexvoda wrote:
             | How about making it turing complete?
        
         | woutr_be wrote:
         | That's clever! I once did the same, except I used a static site
         | generator that I would push to Github and deploy on Netlify.
        
           | iamacyborg wrote:
           | Yeah I suspect you could do something nifty along these lines
           | with Netlify Functions.
        
             | woutr_be wrote:
             | I didn't even use Netlify functions, it was all just HTML
             | and a few lines of JavaScript.
        
           | robbiemitchell wrote:
           | I'd love to know more about how you did this!
        
             | woutr_be wrote:
             | It's really simple; I used Jekyll, every URL was a post
             | with a simple template that did the redirection.
        
       | oneeyedpigeon wrote:
       | There's a lot of useful stuff to learn from this tiny example,
       | providing you look at it more as a learning exercise than a
       | production enterprise solution!
       | 
       | OP, how does this get around CORS?
        
         | nelsontky wrote:
         | The github api does not care about your origin so that wasn't
         | something I had to deal with! If I had to deal with something
         | like that, my best option would be to use a proxy server, which
         | would arguably negate the whole point of this "serverless"
         | hack.
        
           | oneeyedpigeon wrote:
           | Your browser should, though. I would expect the fetch()
           | request from nlsn.cf to github.com to throw a security error
           | -- presumably, the way custom domains are handled on github
           | pages includes the addition of the custom domain as a trusted
           | source at the github end.
        
             | nelsontky wrote:
             | What I meant was that GitHub's API does not check for the
             | Host header, and the API allows connections from any
             | source. Thus, CORS isn't an issue at all.
        
               | oneeyedpigeon wrote:
               | But the same-origin policy implemented by your browser
               | should prevent the request before it gets anywhere near
               | the API.
        
               | hunter2_ wrote:
               | No, when a script tells a browsers to make a cross-origin
               | request such as a GET or POST, the browser first makes a
               | "pre-flight" request (without the payload) using the
               | OPTIONS method to see what CORS-related response headers
               | come back. If headers are returned that allow for it to
               | proceed, the browser then makes whatever request the
               | script asked for.
               | 
               | The network tab of developer tools should reveal all of
               | this.
        
             | diggan wrote:
             | > Your browser should, though
             | 
             | It should, in the right circumstances. By default, CORS
             | dictates that cross-origin requests should not be allowed.
             | 
             | But sometimes you want that to be possible, so we have
             | headers available to is where we can signal which domains
             | are allowed to access the origin when on another origin.
             | 
             | In the case of the GitHub API, they (GitHub) are setting
             | these headers to allow any origin to access the GitHub API
             | from any other origin, that's why your browser doesn't
             | throw a security error. Check out the various "access-
             | control-*" headers the GitHub API returns as response
             | headers when you use it.
             | 
             | It has nothing to do with custom domains or GitHub Pages,
             | but all to do with CORS and associated headers. You can
             | learn more about CORS here:
             | https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
        
               | oneeyedpigeon wrote:
               | Ah, thanks. I thought they might've had a dynamic list of
               | domains that they add each custom domain too; I guess
               | that would be _enormous_ , even if it sounds a lot more
               | secure than "Access-Control-Allow-Origin: *"!
        
             | detaro wrote:
             | The Github API has CORS setup to allow requests from
             | everywhere. This has nothing to do with being hosted on
             | GitHub Pages.
        
               | diggan wrote:
               | > Github API has CORS setup
               | 
               | I know perfectly fine what you mean here, but in the name
               | of security, it's important to be precise.
               | 
               | All websites and browsers have CORS, one way or another,
               | as CORS is the general concept. By default, only "same-
               | origin" requests are allowed and "cross-origin" requests
               | are disabled. But CORS is still there none the less.
               | 
               | What GitHub has done in this case, is add support for
               | "cross-origin" requests.
               | 
               | Nitpicky maybe, but thought it'd be useful to add to
               | avoid any confusion.
        
             | J-Kuhn wrote:
             | Just a CORS header.
             | 
             | Access-Control-Allow-Origin: _star_
        
       | OJFord wrote:
       | I was sure this was going to use Actions, using Issues is... More
       | elegant I suppose.
       | 
       | Babel though? Packages? JavaScript? This could just be a single
       | HTML file, surely?
        
       | chpmrc wrote:
       | This is brilliant! Especially to distribute branded shortened
       | URLs of the kind {mydomain}/{id} without having to maintain
       | pretty much anything _and_ giving the end user a chance to verify
       | what the URL actually leads to. Thank you!
        
       | pelasaco wrote:
       | Somebody was faster than me https://github.com/nelsontky/gh-
       | pages-url-shortener/issues/1...
        
         | nelsontky wrote:
         | That's a good one fixing now hehe
        
           | pelasaco wrote:
           | thank you for this project. Great idea of how to "hack"
           | around GH. Hope it can be used as inspirations for similar
           | projects!
        
       | quyleanh wrote:
       | It's so cool. I am using https://git.io as url shortener, and now
       | this project makes me reconsider.
       | 
       | What if some of shortener domain so popular that Github takes
       | some action? Like block or ban?
        
         | nelsontky wrote:
         | This is definitely just a fun hack and not meant for
         | production! For production ready short links with low overheads
         | I would personally recommend using Firebase URLs or cloud
         | firestore.
        
         | iainmerrick wrote:
         | I would _hope_ that the most they'd do is limit /throttle the
         | number of new and updated issues. As long as the limit is very
         | generous for a normal project, this sort of thing would still
         | be supported at reasonable usage levels.
         | 
         | Hopefully it wouldn't be considered abuse just by its nature
         | (as opposed to any traffic spikes it might cause). Quite the
         | reverse, this shows off the flexibility of the service!
        
       | belval wrote:
       | Very crafty project, I wonder if there is an awesome-github-pages
       | repo where we could index these GitHub pages projects.
        
       | Jhsto wrote:
       | You could also push static HTML pages to the git root which have,
       | e.g.,
       | 
       | <meta http-equiv="refresh" content="1;
       | url='https://news.ycombinator.com/'" />
       | 
       | in the header.
        
         | chrismorgan wrote:
         | Any particular reason why you wrote 1 rather than 0?
        
           | Jhsto wrote:
           | Not really. Copied it from somewhere else where the
           | placeholder value was 7. 1 came to my mind before 0. Zero
           | seems like it could be UB.
        
             | chrismorgan wrote:
             | Nah, zero just means "redirect after zero seconds", meaning
             | immediately. You definitely want zero.
        
         | wesleytodd wrote:
         | That is how I did this:
         | https://github.com/wesleytodd/short/blob/gh-pages/p2/index.h...
        
         | navanchauhan wrote:
         | I am not familiar with this, could you explain what will
         | happen?
        
           | notRobot wrote:
           | It will redirect to the url.
        
           | lbotos wrote:
           | for browsers that load the page that contains that stanza and
           | respect meta refresh, it will refresh and redirect you to the
           | url=.
        
         | ValentineC wrote:
         | I reckon it'll be possible to "simplify" it even more for an
         | end-user, by making a static site generator generate these
         | redirect HTML files from markdown or a CSV.
        
           | davchana wrote:
           | I did exactly as you said, about a year or two ago, using
           | Jekyll.
           | 
           | https://gitlab.com/davch/static-redirect
        
           | nelsontky wrote:
           | Some guy shared his project in this post that does exactly
           | that! Yes while that is possible and can get to a high level
           | of automation via GitHub actions, the point of my URL
           | shortener was more of people could post a link easily with a
           | simple interface (like the interface for adding a new issue).
           | But if I were operating with a fixed set of short links, then
           | this would have been a good method!
        
       | steerablesafe wrote:
       | Interesting. This could be considered as abuse of github issues
       | though.
        
         | kordlessagain wrote:
         | > could be considered as abuse of github issues though
         | 
         | Like licensing arguments?
        
         | hiccuphippo wrote:
         | The best hack on github issues I know is the trending-repos
         | repo. Just subscribe to the issue of the technologies you care
         | and you'll receive a daily/weekly email with the most starred
         | repos for that period:
         | 
         | https://github.com/vitalets/github-trending-repos/
        
         | OskarS wrote:
         | Yeah, this is like when people built filesystems on top of
         | Gmail attachments in the bad old days before Dropbox.
        
         | nelsontky wrote:
         | Indeed, especially with the recursive link created by someone
         | else (nlsn.cf/6)
         | 
         | GitHub does have a 60 calls per hour API limit so I don't think
         | it affects them as much(?) That being said this project is
         | meant to be for fun and definitely not recommended for
         | production purposes HAHA
        
         | userbinator wrote:
         | I've seen quite a few uses of the issues page as a discussion
         | forum too. I certainly wouldn't consider any of it "abuse",
         | however.
         | 
         | I wonder if anyone has made this observation before in regards
         | to such things: "Anything that can be used to store arbitrary
         | data, will be used to store arbitrary data."
        
         | xwdv wrote:
         | Think of this as the software version of graffiti.
         | 
         | It is an artistic and creative way to shorten urls, but likely
         | won't exist forever. As long as it does though, we can
         | appreciate the art for what it is.
        
       | xendop wrote:
       | This is really cool. I think it might even be possible to improve
       | it further so opening an issue isn't even needed.
       | 
       | My thinking is you could store the links and the corresponding
       | shortened URL lookups as an element in the HTML source itself.
       | You would have a submit input on the page. User enters the url
       | they'd like to shorten (or is pulled from a param). The JS reads
       | that value and then looks it up to see if it already exists in
       | the element you created for storage. If not, it creates a hash as
       | the shortened 'link' and adds it to a hashmap / element. Now this
       | is the crucial part: have JS call the Github Actions API to
       | trigger a workflow (https://docs.github.com/en/free-pro-
       | team@latest/rest/referen...) that puts the updated hashmap (which
       | is a payload for a custom parameter you defined for the GH
       | Action) into a file e.g. `links.json` or even outputted directly
       | into the HTML source. Then have the action commit this file back
       | into the repo. Thus, the flat file in the repo acts as the
       | storage mechanism for the links. From a UX standpoint, this is a
       | little smoother and more cohesive (same site to input & redirect)
       | than having to open a GH issue.
       | 
       | With this approach, you can still have the nlsn.cf short domain
       | redirect as long as you pass the URL params and get them in JS
       | from the location, which it looks like you already do. I might
       | try whipping up a version of this tonight. Thanks for the
       | inspiration!
        
         | nelsontky wrote:
         | Hmm having a GitHub action redeploy the site is not
         | instantaneous and it does take up to 1 minute for the site (and
         | consequently the new short link) to be updated. Nevertheless,
         | that is a sweet idea, and there are other replies that
         | suggested using a static site generator to generate one html
         | file per short link, with each html file containing a
         | "redirect" tag in <head>. This idea can definitely be combined
         | with a GitHub action. Personally I feel that is overkill,
         | because if I were doing something so elaborate, I would have
         | opted for a simpler and more scalable option like Google Cloud
         | Firestore or Firebase URLs
        
       | chrismorgan wrote:
       | This currently uses about 100KB of JavaScript (over 99KiB of
       | polyfills, about 3KiB of actual code), loading the HTML file,
       | then three JavaScript files, then making an API call to GitHub,
       | then _finally_ doing the actual redirect, by a substantially
       | inferior JavaScript technique. Also, it doesn't work on IE
       | because the polyfills were insufficient.
       | 
       | Yes, this is an interesting technical demonstration of a concept,
       | but it also has some rather serious problems, so that I would
       | strongly recommend that no one actually do things this way.
       | 
       | ----
       | 
       | Firstly, the size of the code: I just golfed it for fun, I think
       | this should do for the full document (though I haven't tested
       | it):                 <!doctype html><meta
       | charset=utf-8><title>Redirecting...</title><script>e=new XMLHttpR
       | equest(),e.addEventListener("load",function(){try{if(/^https?:\/\
       | /(?!nlsn\.cf(\/|$))/.test(e=JSON.parse(e.responseText).title))ret
       | urn location.replace(e)}catch(e){}location.replace("/")}),e.open(
       | "GET","https://api.github.com/repos/nelsontky/gh-pages-url-
       | shortener-
       | db/issues/"+location.pathname.split("/")[1]),e.send()</script>
       | 
       | 100KB in four requests, down to 412 bytes in one request (and
       | that 20 bytes of <meta charset=utf-8> isn't even particularly
       | valuable). And it restores support for IE, by using simple
       | regular expression testing instead of `new URL(...)`, which IE
       | never supported. As written, I believe it should work down to
       | IE9, and older could be supported if you replaced the load event
       | handler with an onreadystatechange incantation.
       | 
       | (Other general remarks on the HTML:
       | 
       | 1. In <meta charset="utf-8" />, the trailing slash is completely
       | ignored by the HTML parser; in fact, I reckon using trailing
       | slashes like this is actively slightly harmful, because it
       | misleads you into thinking it closes elements, as in XML, but it
       | doesn't.
       | 
       | 2. On the script elements, type="text/javascript" is the default
       | and thus not needed.
       | 
       | 3. <html>, <head> and <body> wrappings can all be omitted from
       | the source. This one is a bit more subject to taste; I know some
       | like their source to match the parsed document tree, even down to
       | things like writing the <tbody> out even if there is no thead or
       | tfoot. But I myself always omit the end tags on these, and omit
       | the start tags unless they have attributes, which in practice
       | means I always have the <html> for its lang attribute.
       | 
       | )
       | 
       | ----
       | 
       | Secondly, the redirection technique. There are good reasons why
       | you should use HTTP redirects and not JavaScript location.replace
       | for something like this:
       | 
       | 1. If you use JavaScript, any users unable to run the JavaScript
       | are left high and dry. This includes people like me that disable
       | JavaScript by default (I because it makes the web so much faster
       | and less annoying; others for privacy reasons and similar), but
       | it would also help people on poor-quality connections, especially
       | if the JavaScript is loaded in a different connection (which will
       | probably not be the case here), because it's surprisingly common
       | for parts of pages' resources to simply fail to load sometimes on
       | poor-quality connections.
       | 
       | 2. Various tooling like link checkers likewise won't be able to
       | work with this. As it stands, even link checkers that ran
       | JavaScript would fail on this because you're also using
       | location.replace to show the "bad link" error. (Another of my pet
       | peeves: doing a redirect to a "not found" page, rather than
       | serving the "not found" page at the original URL with status code
       | 404.)
       | 
       | 3. It's perfectly feasible for the connection to https://nlsn.cf
       | to have succeeded, but the connection to https://api.github.com
       | to fail. When this happens, you're left trying to decide what to
       | do; and location.replace("/") is a very bad solution, because
       | you've now trashed the URL and I can't even just try reloading
       | the page to see if it works second time round. If you use HTTP
       | redirects, everything will work perfectly in all cases,
       | regardless of which connections succeed or fail.
       | 
       | 4. Browsers have redirect loop detection, but you've opted out of
       | that. In this thread someone pointed out simple loops and you've
       | now tried to work around this by telling it "don't redirect to
       | the same domain", but this really isn't enough: you can easily
       | have A - B - A. If this was done with HTTP redirection, the
       | browser would twig and show an error and stop; but because half
       | of the loop is done with location.replace, this won't be caught.
       | (Also, there are perfectly legitimate cases for a short URL
       | redirecting to another short URL which redirects to a long URL,
       | which this has now broken.)
       | 
       | ----
       | 
       | A more amusing concept that occurs to me is implementing the URL
       | shortener in a service worker, so that you _can_ issue proper
       | HTTP redirects, while doing it only on the client side.
        
         | nelsontky wrote:
         | Thank you for the reply! I definitely learnt a lot from your
         | comprehensive replies. Personally, I am just getting started in
         | web development and I have traditionally written everything
         | with the help of frameworks like ReactJS and the like and the
         | abstractions these frameworks provide means I actually don't
         | know the nitty gritty of how things work. Cross browser
         | compatibility or efficiency was definitely not something I
         | considered and they are definitely very valid considerations.
         | And HTTP redirects via service workers sounds damn interesting!
         | I will go read up on those now! Thank you for the comment I did
         | learn a lot and will work these suggestions into the code base
         | when I do have the time :')
        
       | maxpert wrote:
       | Using GH issues as DB :P I wonder how long before GitHub will
       | notice and shut it down for abuse.
        
         | khalilravanna wrote:
         | Prolly be fine unless for some reason a famous person used it
         | to post a link that got millions of hits in a short time. Then,
         | I would assume pretty quickly if GitHub tracks API use per key.
         | Or maybe it'd just be throttled.
        
       | rahimnathwani wrote:
       | If you prefer Netlify: https://github.com/kentcdodds/netlify-
       | shortener
        
       | priitmaxx wrote:
       | Very smart use! Creative!
        
       | geekodour wrote:
       | Neat project. What were your ideas for storing the content in git
       | version history? (i.e as files itself?)
       | 
       | Shameless plug for a similar project that i did few years back: A
       | (partial) static site generator based on github issues :)
       | https://github.com/geekodour/gitpushblog
        
         | nelsontky wrote:
         | If the links were to be stored in files, I probably would run a
         | GitHub action on every push to statically generate the pages
         | for new links!
        
       | giancarlostoro wrote:
       | I was expecting it to be a way of taking a URL and converting it
       | to a base64 type of format that is stored on the "url" itself and
       | decoded by a simple web page. I have wanted to try to do this for
       | a while, but never saw down to look for an appropriate encoding
       | that somehow also compresses.
       | 
       | I helped someone design a regular URL shortener in PHP before,
       | they're not complicated to implement with a simple MySQL (or even
       | SQLite) database and any language you're familiar with. I have
       | not taken a stab at writing a client-side shortener yet on the
       | other hand.
       | 
       | Edit: clarifying
        
         | hobby-coder-guy wrote:
         | Why would you need a database for that?
        
           | giancarlostoro wrote:
           | I realize I misspoke and update my message about why we used
           | a database. I helped someone do a regular URL shortener, but
           | have always been curious about doing a databaseless / no I/O
           | on any server whatsoever based shortener.
        
         | nelsontky wrote:
         | Base64 would probably be longer than the original URL. I can't
         | really see how short pieces of text (like URLs) could be
         | compressed to become smaller. That being said it's definitely a
         | cool concept! I once worked on a code playground kinda thing
         | for my school and there was a function to share the code
         | written in a URL. How we did it was just to include the whole
         | piece of code as a URL param in base64!
        
           | giancarlostoro wrote:
           | Well that's why I said "type of" but yeah I can't see it
           | either unfortunately, of course, as long as the URL you're
           | trying to shorten isn't too insanely long it might be
           | workable to do some sort of encoding on it.
        
       | eeZah7Ux wrote:
       | 3425 lines in package-lock.json for a "Minimal URL shortener"
       | 
       | https://github.com/nelsontky/gh-pages-url-shortener/blob/mai...
        
         | interactivecode wrote:
         | even though this isn't really a constructive comment, most of
         | that package-lock.json is build tools. If you remove those and
         | only install production packages it's 27 lines:
         | https://gist.github.com/StefKors/3b43896467d05cb1fb693ed0da9...
        
         | nelsontky wrote:
         | I figured that since the dependencies were only used in the
         | build step it's not really considered. That being said, I
         | didn't know ES2015 had `.then()` and was kinda trying out babel
         | since I always used CRA and never knew what was going on behind
         | the scenes. The dependencies were definitely not needed but in
         | the production build, they aren't really "unminimal"
        
         | darkwater wrote:
         | I always wondered if relying so much on external libraries in
         | the long run is more hassle to maintain than doing it by
         | yourself. Security updates will be provided for X major version
         | for a reasonable amount of time, but afterwards you will have
         | to update, check that nothing breaks and update your code as
         | well. Also some of the deps will break regardless of SemVer and
         | you will need to update.
        
           | wwwwwwwww wrote:
           | Sadly, its a lost cause. The result is [left-pad](https://www
           | .theregister.com/2016/03/23/npm_left_pad_chaos/).
        
         | tjelen wrote:
         | And all that is just for being able to write `response = await
         | fetch(...)` instead of `fetch(...).then(...)`.
        
           | nelsontky wrote:
           | My fault. Didn't know that ES2015 actually supported
           | `.then()`. Anyway, this was also an exercise for me to learn
           | about babel (I use CRA all the time so have no idea what is
           | going on behind the scenes) and this was a nice intro!
        
       | wesleytodd wrote:
       | I like mine better :P
       | 
       | https://github.com/wesleytodd/short
        
       | navanchauhan wrote:
       | Shortened link to this discussion: https://nlsn.cf/11
        
       | TimLeland wrote:
       | Better be ready for the malicious links. I'm the developer of
       | https://t.ly/ link shortener. I spend most of my time adding in
       | protection to prevent people from using the service for malicious
       | links.
        
         | nelsontky wrote:
         | Thank you for the advice! I love that domain though, have
         | always been trying to find a 4 character URL shortener since
         | GoDaddy killed x.co. Will definitely use your service more than
         | I use my own HAHA. That being said, my project is not meant to
         | be seriously used, just kinda a cool hack that is not meant to
         | work forever/work reliably. Appreciate your comments and all
         | the best for your service! You just gained one more (non)
         | malicious user!
        
           | TimLeland wrote:
           | Thanks! Your project is really neat. Curious how long github
           | would let it go and if they have a max number of issues. In a
           | short time, T.LY has almost 5 millions short links. I have a
           | lot of users using the shortener from the extension
           | https://t.ly/extension
        
       | AmazingTurtle wrote:
       | Interesting, I just did http://nlsn.cf/54.
       | 
       | I just found a "bug" that can be abused (in chrome at very
       | least).
       | 
       | URL('http:53') returns https://0.0.0.53 (it casts the int32
       | number to an ip address, dont' ask why). But
       | window.location.replace behaves differently and treats it as a
       | relative URL.
        
         | philshem wrote:
         | You should submit this bug as an issue in the repository.
         | 
         | Oh, wait.
        
         | nelsontky wrote:
         | Wow.. I don't even know where to start.. Thanks for the heads
         | up that's cool beans!
        
         | tomcat27 wrote:
         | lol github folks will need to start sanitizing the titles since
         | now its trending on HN.
        
       | josefresco wrote:
       | I setup YOURLS* for a client several years back, worked quite
       | well. Was always a little concerned about privacy/potential for
       | abuse (being self-hosted) but we never had those issues due to
       | the limited use & exposure.
       | 
       | *https://yourls.org
        
         | _eht wrote:
         | I'll second this. A fairly easy to use framework. Not too big
         | that you couldn't read the PHP or make adjustments as needed.
        
         | nelsontky wrote:
         | I do have YOURLS on my personal domain/server. It does work
         | well for me and has no spam as link creation can be made
         | private!
        
       | soheil wrote:
       | This could be implemented on top of any collaborative tool such
       | as Wikipedia or anywhere a user can enter some text something
       | like a comment section. For example instead of creating Github
       | issue every time one could just reply to an existing issue with
       | the desired URL and have the tool redirect to it based on a
       | unique id.
        
       | elondaits wrote:
       | I made a URL shortener for the organization I work at using
       | Amazon S3. I created a bucket that is hosted as a website, to
       | which I upload empty files with the "Redirect" metadata field to
       | indicate the destination.
        
         | thebeardisred wrote:
         | I'm happy I wasn't the only one to do this, especially after
         | seeing this comment:
         | 
         | > Unlike many URL shorteners, this one does not need a database
         | and can be entirely hosted on GitHub pages.
        
       | bigbubba wrote:
       | We have too many URL shorteners already. These things accelerate
       | link rot.
        
         | nelsontky wrote:
         | Indeed and especially with many shorteners not being maintained
         | and going down. That being said, this one is not meant to be an
         | actual URL shortener, but rather, a cool hack and it is not
         | meant to be used widely or used in production.
        
           | bigbubba wrote:
           | Fair enough, I'm all for neat hacks. Link shorteners in
           | general make me concerned since I've encountered more than a
           | few dead ones. It's frustrating to know that the content
           | you're trying to access may very well still be alive, but the
           | only links you have to it are dead because somebody got bored
           | of running the shortener used.
        
       | hyperpallium2 wrote:
       | And by sorting issues and comments by vote, also reddit.
        
       | tutfbhuf wrote:
       | I would find it better if he'd add something like an auto accept
       | pull request bot, that allows you to append a single url (with
       | validation check + rate limiting) to a file, that will be read by
       | the url shortener + auto deploy on new master commit. That would
       | be truly databaseless.
        
         | nelsontky wrote:
         | Well I would believe that even a `json` file or any other form
         | of storage written to disk is considered a database, But your
         | suggestion definitely brings it further away from an actual
         | database!
        
           | tutfbhuf wrote:
           | Well, if by your definition a flat .txt file is considered to
           | be a database then yes.
        
       | VWWHFSfQ wrote:
       | > Unlike many URL shorteners, this one does not need a database
       | and can be entirely hosted on GitHub pages.
       | 
       | it does need a database though. it just uses someone else's
       | database
        
         | veesahni wrote:
         | Just like serverless still has servers, this can be reasonably
         | called dbless :)
        
           | sp332 wrote:
           | Exactly, so let's not repeat that mistake!
        
           | xwdv wrote:
           | Essentially this is the promise of the blockchain. Imagine
           | one massive global database where anyone can store anything
           | in encrypted form. Free, forever.
        
             | logram wrote:
             | I was under the impression that you paid for a transaction.
             | That wouldn't be free, would it?
        
               | sp332 wrote:
               | Paying puts your transaction near the head of the queue.
               | This matters more when there's a backlog. If you're
               | willing to wait for things to clear up, you don't need to
               | pay. https://bitcoinfees.net/
        
             | eloff wrote:
             | There is no free lunch. That goes double for proof of work
             | algorithms.
        
         | fishtoaster wrote:
         | A URL shortener _can_ be done with no database - I did it using
         | only Lambda functions once, but I wouldn 't recommend it. :)
         | https://kevinkuchta.com/2018/03/lambda-only-url-shortener/
        
           | mcintyre1994 wrote:
           | Haha this is fantastic. Are the IDs still coming from that
           | single counter lambda? Or put another way, do you now have
           | 1,750,785 lambdas in your AWS account? :)
        
             | fishtoaster wrote:
             | Yeeeeeeep. :) Someone automated spinning up new IDs at some
             | point and flooded this service with urls. I wrote a script
             | to delete old ones, but it takes a few days to run and I
             | haven't gotten around to letting it finish.
        
           | keanebean86 wrote:
           | I've seen people suggest using pi as a "database." In this
           | instance you could map ranges of pi to characters. Then you
           | search pi until you find the right range. The URL would
           | contain the range(s) needed.
           | 
           | This is terrible and so computationally wasteful. But it's
           | interesting to think about.
        
             | skulk wrote:
             | In a similar vein, almost every algorithm can be converted
             | into a O(1) space version simply by converting it into the
             | dumbest possible search algorithm over the solution space:
             | just sample from the solution space randomly (with a seeded
             | PRNG or something) until you get the right answer.
             | 
             | A well-known example of this is bogosort:
             | https://en.wikipedia.org/wiki/Bogosort
        
               | teraflop wrote:
               | Interestingly, bogosort cannot actually be implemented in
               | constant space -- at least, not if you're talking about a
               | deterministic algorithm. In order for your PRNG to have a
               | large enough state space to cover all possible
               | permutations, it needs O(n log n) bits.
               | 
               | In the Turing machine model of computation, algorithms
               | that use O(1) space are theoretically equivalent to
               | finite state machines (potentially with a very large
               | number of states). Logarithmic space is where things
               | start to get interesting, because it's enough to store a
               | constant number of _pointers_ into an arbitrarily large
               | input.
        
             | earthboundkid wrote:
             | "X in pi" is an interesting thought experiment, but
             | practically speaking, the least efficient way to do
             | anything, since finding a string of N digits in pi will
             | require a search space exponentially much larger than N on
             | average, so it ends up just being an extremely inefficient
             | encoding. A huffman coding + base32/base64 is a better
             | "databaseless" short URL system.
        
             | fishtoaster wrote:
             | Seems technically possible - example.com/12_3456 would
             | calculate out pi, read 12 digits starting at position 3456,
             | then convert those digits to ascii and you'd have your
             | result. Given how far into the digits pi you'd have to go
             | to find the exact right sequence that matches, eg,
             | https://google.com, though, I suspect the resulting
             | position number would be longer than the original url!
             | 
             | Also, conceptually, it seems like you're not so much using
             | pi as a database as you are using it as an encoding
             | mechanism: turning "abc.com" into a string of numbers whose
             | length is relative to the original string. At that point
             | you might as well pick an easier encoding, like base64. :)
        
         | nelsontky wrote:
         | HAHA yes it does opps slightly clickbait
        
           | nvr219 wrote:
           | HAHA roasted
        
       | tomcat27 wrote:
       | nice discovery!!
        
       | known wrote:
       | Isn't https://archive.is better? It also archives the web pages;
        
       | ermik wrote:
       | GitHub really needs to step up its CORS game.
        
         | nelsontky wrote:
         | I am calling GitHub's official API. APIs are not supposed to
         | have any CORS restrictions.
        
         | detaro wrote:
         | Why?
        
       | voldemort1968 wrote:
       | I was just thinking of this the other day, and how I wanted to
       | try doing this without a database. Bravo!
        
       | ffpip wrote:
       | Brilliant. Works well.
       | 
       | But this has a chance of not working since you are doing the
       | redirection client-side. Some addons block 3rd party resources.
       | Looks like you're using the github API and sending the request
       | from the user's browser.
        
         | notRobot wrote:
         | All redirection is client-side. Even 301s are just instructions
         | for the client to open another page, which they are free to
         | ignore.
        
           | oneeyedpigeon wrote:
           | Sometimes you have to mentally translate "client-side" into
           | "JavaScript", then whatever you're reading makes more sense.
        
       | antonpuz wrote:
       | I wonder whether this idea could be taken further and rely on
       | existing redirection service. So you won't host anything.
        
       | [deleted]
        
       | start123 wrote:
       | Since I am running a URL shortener service https://blanq.io, my
       | two cents:
       | 
       | 1. I looked at https://github.com/nelsontky/gh-pages-url-
       | shortener/blob/mai... and it is a basic script that does nothing
       | more than redirection. A lot of URL shorteners on the web do a
       | lot more. Premium ones can track users and route links based on
       | client.
       | 
       | 2. Most of URL shortening audience is non-technical and they
       | usually like to pay and forget about it. Hosting and running your
       | own service is an overhead.
       | 
       | 3. Handling traffic at scale is challenging. So, if you have a
       | lot of hits, I would not advise spending time maintaining the
       | service.
       | 
       | 4. Github can kill this anytime.
       | 
       | That said, this is neat solution for basic needs.
        
         | username_my1 wrote:
         | How come I couldn't find your service when I was looking for
         | alternatives for bitly? The only results I got via Google,
         | product hunt ... services that were overpriced and very
         | limiting (nr of teammates)
        
           | start123 wrote:
           | Also on PH by the way
           | https://www.producthunt.com/posts/blanq/. Will bump you up as
           | paid account for free if you are interested :)
        
           | start123 wrote:
           | I launched this a few months ago so getting to the first page
           | of google search results is a bit challenging.
        
             | ffpip wrote:
             | Maybe allow users to shorten links for free (without
             | account) so that your domain becomes recognizable. bitly
             | became popular that way
             | 
             | And target enterprises with custom URL's. They look very
             | good
             | 
             | Maybe copy some features adjust has (deep linking and
             | redirecting to respective app stores with tracking
             | parameters)
             | 
             | https://www.adjust.com/glossary/deep-linking/
        
               | start123 wrote:
               | Without account, shortening invited spammers and lead to
               | security concerns and it was difficult to deal with that.
               | 
               | Businesses that I target have set up custom domains and
               | reap more benefit from it.
               | 
               | I eventually plan to retire default shortening
               | domain(blanq.io) and only offer custom domains.
        
         | chrisma0 wrote:
         | 1. What's wrong with a "basic" script?
         | 
         | 2. who "likes to pay"? Having a free option is great, no matter
         | whether you're "non-technical" or not...
         | 
         | 3. It's hosted on GH Pages. I think they're pretty okay on the
         | scaling front, what do you think?
         | 
         | 4. Technically yes, as in "they could switch off GH Pages and
         | the API". Not sure how likely that is. Also, the redirections
         | are saved as GH issues
        
           | start123 wrote:
           | 1. Nothing wrong. But there are plenty of things to consider
           | if you need a mature product.
           | 
           | 2. Businesses like to pay.
           | 
           | 3. Github has been bad lately https://www.theregister.com/202
           | 0/07/13/github_takes_some_dow...
        
         | simonklitj wrote:
         | I don't think this is meant to be used by anyone, except as a
         | fun proof-of-concept project, or maybe for a personal
         | collection of URLs.
        
         | nelsontky wrote:
         | Yes I agree with all of the above. And with my fixation on URL
         | shorteners, I did have a dream of creating a full fledged URL
         | shortening service like yours. I wasn't technically skilled
         | enough for that then and thus didn't do it but your site does
         | look great!
        
           | start123 wrote:
           | Thanks. I started this since it had a low-entry barrier but,
           | going from basic to a mature product was quite challenging
           | and a great learning experience personally.
        
         | ffpip wrote:
         | I think the example on your home page would look better as
         | https://mysto.re/buy-shoes
         | 
         | https://en.wikipedia.org/wiki/.re
        
           | start123 wrote:
           | Wow! Thanks. That's way better.
        
             | ffpip wrote:
             | Yeah. It is a popular feature in link shortners. Looks a
             | lot better and has a premium feeling.
             | 
             | Examples are youtu.be , goo.gl , redd.it , cbsn.ws
        
       | ROARosen wrote:
       | Not working now...
        
       | geongeorgek wrote:
       | This is a cool project to play around and do but I don't think
       | people will use it in a practical sense
        
       | ghego1 wrote:
       | Congrats! I really love this concept for two reasons.
       | 
       | First I'm always fascinated by smart solutions that make use of
       | existing free (as in beer) infrastructures to provide a service
       | with open-source software. In this way we truly get FOSS.
       | 
       | Second, I really like the idea that the information on where the
       | shortened url redirects to is publicly available. I know that
       | solutions like bitly.com do provide a way to preview the shortend
       | url, but I think this is just more transparent, although
       | admittedly a little bit less obvious.
        
         | Phemist wrote:
         | You raise a point that strikes me as odd, but perhaps I am not
         | up to date on what is considered FOSS nowadays.
         | 
         | In what way will this lead to `truly` FOSS? Sure, the URL
         | shortener project is open-source, but neither Github Pages nor
         | Github Issues are free-as-in-libre open-source projects. What
         | is being show-cased here is a neat idea, but ultimately the
         | dependency on Github's Pages and Issues will make it difficult
         | to port to other systems, thus you are not really free to do
         | with as you please.
         | 
         | So, while the URL shortener program itself is FOSS with all the
         | right licenses, doesn't the direction you are proposing lead to
         | more capture by these non-free platforms, as the value they
         | offer for free-as-in-beer becomes more and more difficult to
         | ignore?
        
       | brunoluiz wrote:
       | That is quite interesting. Only issue is to rely on Github Issues
       | for it (it might get messy with too many issues opened).
       | 
       | I had this same ~dream of hosting a URL Shortener statically,
       | which lead me to create URLZap. The difference is that it relies
       | on a config file and it can be used on any code repository
       | service https://github.com/brunoluiz/urlzap
        
         | nelsontky wrote:
         | Cool project! Thanks for sharing! Yea the reason why I chose
         | GitHub issues as a "database" was because it is simple to add a
         | short link that manner. Definitely may get messy and there are
         | other shortcomings like the lack of ability to indicate/reuse
         | aliases. The other way to run a URL shortener service with low
         | effort would be to use Firebase. Your idea is a cool one, love
         | it especially since it uses GitHub actions too!
        
       ___________________________________________________________________
       (page generated 2020-11-16 21:01 UTC)