Introduction
- It is not necessary be a deeplink, yet deeplink is likely to be a route
- It is the direction logic inside router
- For mobApp, if deeplink is not exposed, you can skip this part
- For webApp, you always need to cope with deeplink
- There is a number of options for SSR
- Statgen + S3 / CF
- Next.js
- Express + ejs / any template engine
Design principle: Simplicity
Should be as flat as possible, as short as possible. If you are composing a youtube-like website,
- v is definitely significant enough to replace video
- For the sake of CDN setting, adding
/me
or/session
as prefix might simplify our workflow, yet you can omit if you want - pp is definitely not appropriate and is hardy recognised as private policy, and hyperlink is always come with underline, so the use of
_
in URL should be avoided
Case | Best | Good | Fair |
---|---|---|---|
Video | /v/:slug, /:id | /video/:slug | /watch-a-video/:slug |
My history | /history | /me/history | /myaccount/history |
Static page: private policy | /s/private-policy | /s/private_policy | /static/pp |
Design principle: Slug first
You are building a website selling local SIM to travellers. Behind the user interface, you have the daypass ID, ZA001
, associated to Australia and a few other countries using ISO3166 country code. However, ZA001
and au
is meaningless to end-user, and daypass may be too professional to read
Best | Good | Fair |
---|---|---|
/daypass/australia, /travel-to-australia | /daypass/au, | /daypass/ZA001?selection=au |
Design principle: Always use <base>
<html>
<head>
<base href="/" />
</head>
</html>
Design principle: Always deploy with SSR
At the moment of writing this article, only Google showed me the power of reading meta tag mutated by JS, so it is beneficial to use SSR
// A typical template in ejs
<html>
<head>
<base href="/" />
<title><%- pageTitle %> | <%- siteTitle %></title>
<meta content="<%- metaTagsDescription %>" name="description" />
<meta content="<%- metaTagsRobots %>" name="robots" />
<!-- Facebook meta tags-->
<meta property="og:type" content="<%- metaTagsType %>" />
<meta property="og:title" content="<%- metaTagsTitle %>" />
<meta property="og:image" content="<%- metaTagsImg %>" />
<meta property="og:url" content="<%- metaTagsUrl %>" />
<meta property="og:description" content="<%- metaTagsDescription %>" />
<!-- Schema.org markup for Google+ -->
<meta itemprop="name" content="<%- metaTagsName %>" />
<meta itemprop="description" content="<%- metaTagsDescription %>" />
<meta itemprop="image" content="<%- metaTagsImg %>" />
<!-- Twitter Card data -->
<meta name="twitter:card" content="<%- metaTagsImg %>" />
<meta name="twitter:site" content="<%- metaTagsSite %>"/>
<meta name="twitter:url" content="<%- metaTagsUrl %>" />
<meta name="twitter:title" content="<%- metaTagsTitle %>" />
<meta name="twitter:description" content="<%- metaTagsDescription %>" />
<meta name="twitter:image" content="<%- metaTagsImg %>" />
</head>
<body>
<script>
window.__PRELOADED_STATE__ = <%- JSON.stringify(initialState) %>
</script>
</body>
</html>