-
Notifications
You must be signed in to change notification settings - Fork 70
Hono server / SEO + improvements #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c8ade33
c72d034
0b14045
624781c
aa06fea
3c6b9be
05907e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # Add your env variables here | ||
| DEPLOYMENT_ENV="staging" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| # Add your env variables here | ||
| # Add your env variables here | ||
| DEPLOYMENT_ENV="staging" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,4 @@ | ||
| { | ||
| "editor.defaultFormatter": "biomejs.biome", | ||
| "editor.formatOnSave": true, | ||
| "editor.formatOnType": false, | ||
| "editor.renderWhitespace": "all", | ||
|
|
@@ -25,10 +24,19 @@ | |
| "[yaml]": { | ||
| "editor.defaultFormatter": "redhat.vscode-yaml" | ||
| }, | ||
| "[typescriptreact]": { | ||
| "biome.enabled": true, | ||
| "editor.defaultFormatter": "biomejs.biome", | ||
| "[javascript][typescript][typescriptreact][javascriptreact][json][jsonc][vue][astro][svelte][css][graphql]": { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I get it its unfortunately needed due to VSCode or Biome bug(s) on windows, but it makes me sad ;) - i never had problems with the previous config. But yeah,... if it then works also on windows all the time its good then.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm this wasn't meant to be here I was testing the biome vs code extension on the repo and left it in by accident, but tbh I'm still having problems sometimes due to the extension, I think they have some bugs that makes it not work on windows in case of some crashes or something |
||
| "editor.defaultFormatter": "biomejs.biome" | ||
| }, | ||
| "[typescript]": { | ||
| "editor.defaultFormatter": "biomejs.biome" | ||
| "explorer.fileNesting.patterns": { | ||
| "*.ts": "${basename}.*.${extname}", | ||
| ".env": ".env.*", | ||
| "*.tsx": "${basename}.*.${extname},${basename}.*.ts", | ||
| "package.json": "*.json, *.yml, *.config.js, *.config.ts, *.yaml", | ||
| "readme*": "AUTHORS, Authors, BACKERS*, Backers*, CHANGELOG*, CITATION*, CODEOWNERS, CODE_OF_CONDUCT*, CONTRIBUTING*, CONTRIBUTORS, COPYING*, CREDITS, Changelog*, Citation*, Code_Of_Conduct*, Codeowners, Contributing*, Contributors, Copying*, Credits, GOVERNANCE.MD, Governance.md, HISTORY.MD, History.md, LICENSE*, License*, MAINTAINERS, Maintainers, README-*, README_*, RELEASE_NOTES*, ROADMAP.MD, Readme-*, Readme_*, Release_Notes*, Roadmap.md, SECURITY.MD, SPONSORS*, Security.md, Sponsors*, authors, backers*, changelog*, citation*, code_of_conduct*, codeowners, contributing*, contributors, copying*, credits, governance.md, history.md, license*, maintainers, readme-*, readme_*, release_notes*, roadmap.md, security.md, sponsors*", | ||
| "Readme*": "AUTHORS, Authors, BACKERS*, Backers*, CHANGELOG*, CITATION*, CODEOWNERS, CODE_OF_CONDUCT*, CONTRIBUTING*, CONTRIBUTORS, COPYING*, CREDITS, Changelog*, Citation*, Code_Of_Conduct*, Codeowners, Contributing*, Contributors, Copying*, Credits, GOVERNANCE.MD, Governance.md, HISTORY.MD, History.md, LICENSE*, License*, MAINTAINERS, Maintainers, README-*, README_*, RELEASE_NOTES*, ROADMAP.MD, Readme-*, Readme_*, Release_Notes*, Roadmap.md, SECURITY.MD, SPONSORS*, Security.md, Sponsors*, authors, backers*, changelog*, citation*, code_of_conduct*, codeowners, contributing*, contributors, copying*, credits, governance.md, history.md, license*, maintainers, readme-*, readme_*, release_notes*, roadmap.md, security.md, sponsors*", | ||
| "README*": "AUTHORS, Authors, BACKERS*, Backers*, CHANGELOG*, CITATION*, CODEOWNERS, CODE_OF_CONDUCT*, CONTRIBUTING*, CONTRIBUTORS, COPYING*, CREDITS, Changelog*, Citation*, Code_Of_Conduct*, Codeowners, Contributing*, Contributors, Copying*, Credits, GOVERNANCE.MD, Governance.md, HISTORY.MD, History.md, LICENSE*, License*, MAINTAINERS, Maintainers, README-*, README_*, RELEASE_NOTES*, ROADMAP.MD, Readme-*, Readme_*, Release_Notes*, Roadmap.md, SECURITY.MD, SPONSORS*, Security.md, Sponsors*, authors, backers*, changelog*, citation*, code_of_conduct*, codeowners, contributing*, contributors, copying*, credits, governance.md, history.md, license*, maintainers, readme-*, readme_*, release_notes*, roadmap.md, security.md, sponsors*", | ||
|
Comment on lines
+37
to
+39
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have you tested/checked if this setting is case sensitive?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I took it from Ant Fu repo, I'd assume he did |
||
| "Dockerfile": "*.dockerfile, .devcontainer.*, .dockerignore, captain-definition, compose.*, docker-compose.*, dockerfile*" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| import { z } from "zod" | ||
|
|
||
| const envSchema = z.object({ | ||
| NODE_ENV: z.enum(["development", "production", "test"]), | ||
| DEPLOYMENT_ENV: z.enum(["staging", "production"]), | ||
| }) | ||
|
|
||
| type APP_ENV = z.infer<typeof envSchema> | ||
| let env: APP_ENV | ||
| /** | ||
| * Helper method used for initializing .env vars in your entry.server.ts file. It uses | ||
| * zod to validate your .env and throws if it's not valid. | ||
| * @returns Initialized env vars | ||
| */ | ||
| export const initEnv = () => { | ||
| const envData = envSchema.safeParse(process.env) | ||
|
|
||
| if (!envData.success) { | ||
| console.error("❌ Invalid environment variables:", envData.error.flatten().fieldErrors) | ||
| throw new Error("Invalid environment variables") | ||
| } | ||
|
|
||
| env = envData.data | ||
|
|
||
| // Do not log the message when running tests | ||
| if (env.NODE_ENV !== "test") { | ||
| console.log("✅ Environment variables loaded successfully") | ||
| } | ||
| return envData.data | ||
| } | ||
|
|
||
| /** | ||
| * Helper method for you to return client facing .env vars, only return vars that are needed on the client. | ||
| * Otherwise you would expose your server vars to the client if you returned them from here as this is | ||
| * directly sent in the root to the client and set on the window.env | ||
| * @returns Subset of the whole process.env to be passed to the client and used there | ||
| */ | ||
| export const getClientEnv = () => { | ||
| const serverEnv = env | ||
| return { | ||
| NODE_ENV: serverEnv.NODE_ENV, | ||
| } | ||
| } | ||
|
|
||
| type CLIENT_ENV = ReturnType<typeof getClientEnv> | ||
|
|
||
| declare global { | ||
| interface Window { | ||
| env: CLIENT_ENV | ||
| } | ||
| namespace NodeJS { | ||
| interface ProcessEnv extends APP_ENV {} | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # Localization | ||
|
|
||
| Localization works by using the `i18next` package. Everything is configured inside of this folder. | ||
| The localization works by using the `/resources/locales` folder. This folder contains all the translations for the different languages. You can add new translations by adding new files to this folder and then changing the `resources.ts` file to include the new language. | ||
|
|
||
| The server part is set up in the `entry.server.tsx` file, and the client part, conversely, is in the `entry.client.tsx` file and also the `root.tsx` file. | ||
|
|
||
| The language is changed by setting the `lng` search parameter in the url. | ||
|
|
||
| ## Server-side | ||
|
|
||
| Due to the fact that the server does not care about loading in additional resources as they are not send over the wire we | ||
| pass in `resources` to the `i18next` instance. This provides all the languages to your server which allows it to render | ||
| the correct language on the server. | ||
|
|
||
| ## Client-side | ||
|
|
||
| The client-side is a bit more complicated. We do not want to load in all the languages on the client side as it would | ||
| be a lot of requests. Instead, we use the fetch backend to load in the language files on the client side. We have a resource route inside of the `routes` directory which is in charge of loading in the resources. This route is called `resource.locales` and it is used to load in the languages. The `resource.locales` route is set up to only load in the languages and namespaces that are needed. In production we cache these responses and in development we don't cache them. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import { generateRobotsTxt } from "@forge42/seo-tools/robots" | ||
| import type { LoaderFunctionArgs } from "@remix-run/node" | ||
| import { createDomain } from "~/utils/http" | ||
|
|
||
| export async function loader({ request }: LoaderFunctionArgs) { | ||
| const isProductionDeployment = process.env.DEPLOYMENT_ENV === "production" | ||
| const domain = createDomain(request) | ||
| const robotsTxt = generateRobotsTxt([ | ||
| { | ||
| userAgent: "*", | ||
| [isProductionDeployment ? "allow" : "disallow"]: ["/"], | ||
| sitemap: [`${domain}/sitemap-index.xml`], | ||
| }, | ||
| ]) | ||
| return new Response(robotsTxt, { | ||
| headers: { | ||
| "Content-Type": "text/plain", | ||
| }, | ||
| }) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why removed?