From 28dc807af9e405ed3d3692a224f10811fd9f9e4a Mon Sep 17 00:00:00 2001 From: Krzysztof Kocot <“k.kocot0@gmail.com”> Date: Tue, 16 Sep 2025 09:58:34 +0200 Subject: [PATCH 01/70] App router layout with test page --- apps/blog/app/layout.tsx | 36 ++++++++++ apps/blog/app/providers.tsx | 21 ++++++ apps/blog/app/test/page.tsx | 6 ++ apps/blog/i18n/client.ts | 50 ++++++++++++++ apps/blog/i18n/server.ts | 27 ++++++++ apps/blog/i18n/settings.ts | 16 +++++ apps/blog/next.config.js | 20 ++++-- apps/blog/package.json | 1 + .../smart-signer/lib/auth/use-user-client.ts | 64 ++++++++++++++++++ pnpm-lock.yaml | 67 +++++++++++-------- 10 files changed, 273 insertions(+), 35 deletions(-) create mode 100644 apps/blog/app/layout.tsx create mode 100644 apps/blog/app/providers.tsx create mode 100644 apps/blog/app/test/page.tsx create mode 100644 apps/blog/i18n/client.ts create mode 100644 apps/blog/i18n/server.ts create mode 100644 apps/blog/i18n/settings.ts create mode 100644 packages/smart-signer/lib/auth/use-user-client.ts diff --git a/apps/blog/app/layout.tsx b/apps/blog/app/layout.tsx new file mode 100644 index 000000000..b7cafd7f5 --- /dev/null +++ b/apps/blog/app/layout.tsx @@ -0,0 +1,36 @@ +'use client'; + +import { Providers } from './providers'; +import '@hive/tailwindcss-config/globals.css'; +import Head from 'next/head'; +import { Toaster } from '@ui/components/toaster'; +import { useTheme } from 'next-themes'; +import { ModalContainer } from '@smart-signer/components/modal-container'; +import { TailwindIndicator } from '../components/tailwind-indicator'; +import { ReactNode } from 'react'; + +export default function RootLayout({ children }: { children: ReactNode }) { + const { resolvedTheme } = useTheme(); + + return ( + + + + + +
+
+ + <> + {children} + + + + + +
+
+ + + ); +} diff --git a/apps/blog/app/providers.tsx b/apps/blog/app/providers.tsx new file mode 100644 index 000000000..2a8e4a29e --- /dev/null +++ b/apps/blog/app/providers.tsx @@ -0,0 +1,21 @@ +'use client'; + +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { ThemeProvider } from '../components/theme-provider'; +import { SignerProvider } from '@smart-signer/components/signer-provider'; + +interface ProvidersProps { + children: React.ReactNode; +} + +export const Providers = ({ children }: ProvidersProps) => { + const queryClient = new QueryClient(); + + return ( + + + {children} + + + ); +}; diff --git a/apps/blog/app/test/page.tsx b/apps/blog/app/test/page.tsx new file mode 100644 index 000000000..f790883d5 --- /dev/null +++ b/apps/blog/app/test/page.tsx @@ -0,0 +1,6 @@ +'use client'; + +const Page = () => { + return
Blog Page
; +}; +export default Page; diff --git a/apps/blog/i18n/client.ts b/apps/blog/i18n/client.ts new file mode 100644 index 000000000..233afb6fb --- /dev/null +++ b/apps/blog/i18n/client.ts @@ -0,0 +1,50 @@ +'use client'; + +import { useEffect, useLayoutEffect, useState } from 'react'; +import i18next from 'i18next'; +import { initReactI18next, useTranslation as useTranslationOrg } from 'react-i18next'; +import resourcesToBackend from 'i18next-resources-to-backend'; +import { getOptions, languages, cookieName, defaultLocale } from './settings'; +import { getCookie } from '@smart-signer/lib/utils'; +import { isServer } from '@tanstack/react-query'; + +i18next + .use(initReactI18next) + .use( + resourcesToBackend( + (language: string, namespace: string) => import(`../locales/${language}/${namespace}.json`) + ) + ) + .init({ + ...getOptions(), + lng: undefined, // let detect the language on client side + detection: { + order: ['path', 'htmlTag', 'cookie', 'navigator'] + }, + preload: isServer ? languages : [] + }); + +export function useTranslation(ns: string, options?: any) { + const lng = getCookie(cookieName); + const ret = useTranslationOrg(ns, options); + + const { i18n } = ret; + if (isServer && lng && i18n.resolvedLanguage !== lng) { + i18n.changeLanguage(lng); + } else { + // eslint-disable-next-line react-hooks/rules-of-hooks + const [activeLng, setActiveLng] = useState(i18n.resolvedLanguage); + // eslint-disable-next-line react-hooks/rules-of-hooks + useEffect(() => { + if (activeLng === i18n.resolvedLanguage) return; + setActiveLng(i18n.resolvedLanguage); + }, [activeLng, i18n.resolvedLanguage]); + // eslint-disable-next-line react-hooks/rules-of-hooks + useEffect(() => { + if (!lng || i18n.resolvedLanguage === lng) return; + i18n.changeLanguage(lng); + }, [lng, i18n]); + // eslint-disable-next-line react-hooks/rules-of-hooks + } + return ret; +} diff --git a/apps/blog/i18n/server.ts b/apps/blog/i18n/server.ts new file mode 100644 index 000000000..42a2d73b8 --- /dev/null +++ b/apps/blog/i18n/server.ts @@ -0,0 +1,27 @@ +import { createInstance } from 'i18next'; +import resourcesToBackend from 'i18next-resources-to-backend'; +import { initReactI18next } from 'react-i18next/initReactI18next'; +import { getOptions, cookieName, defaultLocale } from './settings'; +import { cookies } from 'next/headers'; + +const initI18next = async (lng: string, ns: string) => { + const i18nInstance = createInstance(); + await i18nInstance + .use(initReactI18next) + .use( + resourcesToBackend( + (language: string, namespace: string) => import(`../locales/${language}/${namespace}.json`) + ) + ) + .init(getOptions(lng, ns)); + return i18nInstance; +}; + +export async function useTranslation(ns: string, options: any = {}) { + const lng = cookies().get(cookieName)?.value ?? defaultLocale; + const i18nextInstance = await initI18next(lng, ns); + return { + t: i18nextInstance.getFixedT(lng, Array.isArray(ns) ? ns[0] : ns, options.keyPrefix), + i18n: i18nextInstance + }; +} diff --git a/apps/blog/i18n/settings.ts b/apps/blog/i18n/settings.ts new file mode 100644 index 000000000..61d717d7a --- /dev/null +++ b/apps/blog/i18n/settings.ts @@ -0,0 +1,16 @@ +export const defaultLocale = 'en'; +export const languages = ['ar', 'en', 'es', 'fr', 'it', 'ja', 'pl', 'ru', 'zh']; +export const defaultNS = 'common_blog'; +export const cookieName = 'NEXT_LOCALE'; + +export function getOptions(lng = defaultLocale, ns = defaultNS) { + return { + // debug: true, + supportedLngs: languages, + fallbackLng: defaultLocale, + lng, + fallbackNS: defaultNS, + defaultNS, + ns + }; +} diff --git a/apps/blog/next.config.js b/apps/blog/next.config.js index 9e62d7f9c..c24f8b76a 100644 --- a/apps/blog/next.config.js +++ b/apps/blog/next.config.js @@ -1,5 +1,4 @@ const path = require('path'); -const withTM = require('next-transpile-modules')(['@hive/smart-signer', '@hive/ui', '@hive/transaction', '@hive/renderer', '@hive/middleware']); const CopyPlugin = require('copy-webpack-plugin'); const removeImports = require('next-remove-imports')(); const withPWA = require('next-pwa')({ @@ -32,11 +31,11 @@ const nextConfig = { headers: [ { key: 'Content-Type', - value: 'application/javascript; charset=utf-8', + value: 'application/javascript; charset=utf-8' }, { key: 'Cache-Control', - value: 'no-cache, no-store, must-revalidate, max-age=0', + value: 'no-cache, no-store, must-revalidate, max-age=0' } ] }, @@ -45,17 +44,24 @@ const nextConfig = { headers: [ { key: 'Content-Type', - value: 'application/javascript; charset=utf-8', + value: 'application/javascript; charset=utf-8' }, { key: 'Cache-Control', - value: 'no-cache, no-store, must-revalidate, max-age=0', + value: 'no-cache, no-store, must-revalidate, max-age=0' } ] } - ]; }, + transpilePackages: [ + '@hive/smart-signer', + '@hive/ui', + '@hive/transaction', + '@hive/renderer', + '@hive/middleware' + ], + async rewrites() { return [ { @@ -112,4 +118,4 @@ const nextConfig = { const withBundleAnalyzer = require('@next/bundle-analyzer')({ enabled: process.env.ANALYZE === 'true' }); -module.exports = withPWA(withTM(withBundleAnalyzer(removeImports(nextConfig)))); +module.exports = withPWA(withBundleAnalyzer(removeImports(nextConfig))); diff --git a/apps/blog/package.json b/apps/blog/package.json index ed9df7353..1645f14bb 100644 --- a/apps/blog/package.json +++ b/apps/blog/package.json @@ -62,6 +62,7 @@ "http-errors": "^2.0.0", "i": "^0.3.7", "i18next": "^23.7.9", + "i18next-resources-to-backend": "^1.2.1", "iron-session": "^8.0.1", "lucide-react": "^0.259.0", "moment": "^2.29.4", diff --git a/packages/smart-signer/lib/auth/use-user-client.ts b/packages/smart-signer/lib/auth/use-user-client.ts new file mode 100644 index 000000000..5223435ab --- /dev/null +++ b/packages/smart-signer/lib/auth/use-user-client.ts @@ -0,0 +1,64 @@ +'use client'; +import { useEffect } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import { useRouter } from 'next/navigation'; +import { QUERY_KEY } from '@smart-signer/lib/query-keys'; +import * as userLocalStorage from './user-localstore'; +import { useIsMounted, useLocalStorage } from 'usehooks-ts'; +import { fetchJson } from '@smart-signer/lib/fetch-json'; +import { defaultUser } from '@smart-signer/lib/auth/utils'; +import { getLogger } from '@ui/lib/logging'; +import { User } from '@smart-signer/types/common'; + +const logger = getLogger('app'); + +interface IUseUser { + user: User; +} + +async function getUser(): Promise { + return await fetchJson(`/api/users/me`); +} + +export function useUserClient({ redirectTo = '', redirectIfFound = false } = {}): IUseUser { + // if (isServer) return { user: defaultUser }; + const isMounted = useIsMounted(); + const [storedUser, storeUser] = useLocalStorage('user', defaultUser); + const { data: user } = useQuery([QUERY_KEY.user], async (): Promise => getUser(), { + refetchOnMount: false, + refetchOnWindowFocus: false, + refetchOnReconnect: false, + initialData: storedUser, + onError: () => { + storeUser(defaultUser); + } + }); + + const router = useRouter(); + + useEffect(() => { + userLocalStorage.saveUser(user || defaultUser); + }, [user]); + + useEffect(() => { + // If no redirect needed, just return (example: already on + // /dashboard). If user data not yet there (fetch in progress, + // logged in or not) then don't do anything yet. + if (!redirectTo || !user) { + return; + } + + if ( + // If redirectTo is set, redirect if the user was not found. + (redirectTo && !redirectIfFound && !user?.isLoggedIn) || + // If redirectIfFound is also set, redirect if the user was found. + (redirectIfFound && user?.isLoggedIn) + ) { + router.push(redirectTo); + } + }, [user, redirectIfFound, redirectTo, router]); + + return { + user: !isMounted() || !user ? defaultUser : user + }; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd0b62f54..6eb8fc2ec 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -256,6 +256,9 @@ importers: i18next: specifier: ^23.7.9 version: 23.16.8 + i18next-resources-to-backend: + specifier: ^1.2.1 + version: 1.2.1 iron-session: specifier: ^8.0.1 version: 8.0.4 @@ -473,13 +476,13 @@ importers: version: 8.57.1 eslint-config-next: specifier: latest - version: 15.4.6(eslint@8.57.1)(typescript@5.5.3) + version: 15.5.3(eslint@8.57.1)(typescript@5.5.3) eslint-config-prettier: specifier: latest version: 10.1.8(eslint@8.57.1) eslint-config-turbo: specifier: latest - version: 2.5.5(eslint@8.57.1)(turbo@2.3.3) + version: 2.5.6(eslint@8.57.1)(turbo@2.3.3) eslint-plugin-react: specifier: latest version: 7.37.5(eslint@8.57.1) @@ -640,7 +643,7 @@ importers: version: 3.6.2 ts-loader: specifier: ^9.5.1 - version: 9.5.2(typescript@5.5.3)(webpack@5.92.1) + version: 9.5.2(typescript@5.5.3)(webpack@5.92.1(webpack-cli@5.1.4)) ts-node: specifier: 10.9.2 version: 10.9.2(@types/node@20.14.10)(typescript@5.5.3) @@ -2031,8 +2034,8 @@ packages: '@next/env@14.2.23': resolution: {integrity: sha512-CysUC9IO+2Bh0omJ3qrb47S8DtsTKbFidGm6ow4gXIG6reZybqxbkH2nhdEm1tC8SmgzDdpq3BIML0PWsmyUYA==} - '@next/eslint-plugin-next@15.4.6': - resolution: {integrity: sha512-2NOu3ln+BTcpnbIDuxx6MNq+pRrCyey4WSXGaJIyt0D2TYicHeO9QrUENNjcf673n3B1s7hsiV5xBYRCK1Q8kA==} + '@next/eslint-plugin-next@15.5.3': + resolution: {integrity: sha512-SdhaKdko6dpsSr0DldkESItVrnPYB1NS2NpShCSX5lc7SSQmLZt5Mug6t2xbiuVWEVDLZSuIAoQyYVBYp0dR5g==} '@next/swc-darwin-arm64@14.2.23': resolution: {integrity: sha512-WhtEntt6NcbABA8ypEoFd3uzq5iAnrl9AnZt9dXdO+PZLACE32z3a3qA5OoV20JrbJfSJ6Sd6EqGZTrlRnGxQQ==} @@ -5237,8 +5240,8 @@ packages: engines: {node: '>=6.0'} hasBin: true - eslint-config-next@15.4.6: - resolution: {integrity: sha512-4uznvw5DlTTjrZgYZjMciSdDDMO2SWIuQgUNaFyC2O3Zw3Z91XeIejeVa439yRq2CnJb/KEvE4U2AeN/66FpUA==} + eslint-config-next@15.5.3: + resolution: {integrity: sha512-e6j+QhQFOr5pfsc8VJbuTD9xTXJaRvMHYjEeLPA2pFkheNlgPLCkxdvhxhfuM4KGcqSZj2qEnpHisdTVs3BxuQ==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 || ^9.0.0 typescript: '>=3.3.1' @@ -5258,8 +5261,8 @@ packages: peerDependencies: eslint: '>=7.0.0' - eslint-config-turbo@2.5.5: - resolution: {integrity: sha512-23lKrCr66HQR62aa94n2dBGUUFz0GzM6N1KwmcREZHxomZ5Ik2rDm00wAz95lOEkhzSt6IaxW00Uz0az/Fcq5Q==} + eslint-config-turbo@2.5.6: + resolution: {integrity: sha512-1EV/UqdKE75st9q6y0MCxz7qp2v7RyGvbQsMLSuCz+VH8ScnSfmhd8FcAbqx3BshCy5IluujzMB6T5iCgL3/sA==} peerDependencies: eslint: '>6.6.0' turbo: '>2.0.0' @@ -5370,8 +5373,8 @@ packages: eslint-plugin-security@1.7.1: resolution: {integrity: sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==} - eslint-plugin-turbo@2.5.5: - resolution: {integrity: sha512-IlN65X6W7rgK88u5xl1xC+7FIGKA7eyaca0yxZQ9CBNV6keAaqtjZQLw8ZfXdv7T+MzTLYkYOeOHAv8yCRUx4Q==} + eslint-plugin-turbo@2.5.6: + resolution: {integrity: sha512-KUDE23aP2JV8zbfZ4TeM1HpAXzMM/AYG/bJam7P4AalUxas8Pd/lS/6R3p4uX91qJcH1LwL4h0ED48nDe8KorQ==} peerDependencies: eslint: '>6.6.0' turbo: '>2.0.0' @@ -6144,6 +6147,9 @@ packages: i18next-fs-backend@2.6.0: resolution: {integrity: sha512-3ZlhNoF9yxnM8pa8bWp5120/Ob6t4lVl1l/tbLmkml/ei3ud8IWySCHt2lrY5xWRlSU5D9IV2sm5bEbGuTqwTw==} + i18next-resources-to-backend@1.2.1: + resolution: {integrity: sha512-okHbVA+HZ7n1/76MsfhPqDou0fptl2dAlhRDu2ideXloRRduzHsqDOznJBef+R3DFZnbvWoBW+KxJ7fnFjd6Yw==} + i18next@23.16.8: resolution: {integrity: sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==} @@ -9102,6 +9108,7 @@ packages: source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} + deprecated: The work that was done in this beta branch won't be included in future versions sourcemap-codec@1.4.8: resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} @@ -11831,7 +11838,7 @@ snapshots: '@next/env@14.2.23': {} - '@next/eslint-plugin-next@15.4.6': + '@next/eslint-plugin-next@15.5.3': dependencies: fast-glob: 3.3.1 @@ -13821,17 +13828,17 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.92.1)': + '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack@5.92.1))(webpack@5.92.1(webpack-cli@5.1.4))': dependencies: webpack: 5.92.1(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack@5.92.1) - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.92.1)': + '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack@5.92.1))(webpack@5.92.1(webpack-cli@5.1.4))': dependencies: webpack: 5.92.1(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack@5.92.1) - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack@5.92.1)': + '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack@5.92.1))(webpack@5.92.1(webpack-cli@5.1.4))': dependencies: webpack: 5.92.1(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack@5.92.1) @@ -15444,9 +15451,9 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-next@15.4.6(eslint@8.57.1)(typescript@5.5.3): + eslint-config-next@15.5.3(eslint@8.57.1)(typescript@5.5.3): dependencies: - '@next/eslint-plugin-next': 15.4.6 + '@next/eslint-plugin-next': 15.5.3 '@rushstack/eslint-patch': 1.10.5 '@typescript-eslint/eslint-plugin': 8.20.0(@typescript-eslint/parser@8.20.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1)(typescript@5.5.3) '@typescript-eslint/parser': 8.20.0(eslint@8.57.1)(typescript@5.5.3) @@ -15472,10 +15479,10 @@ snapshots: dependencies: eslint: 8.57.0 - eslint-config-turbo@2.5.5(eslint@8.57.1)(turbo@2.3.3): + eslint-config-turbo@2.5.6(eslint@8.57.1)(turbo@2.3.3): dependencies: eslint: 8.57.1 - eslint-plugin-turbo: 2.5.5(eslint@8.57.1)(turbo@2.3.3) + eslint-plugin-turbo: 2.5.6(eslint@8.57.1)(turbo@2.3.3) turbo: 2.3.3 eslint-import-resolver-node@0.3.9: @@ -15522,7 +15529,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.20.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.20.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: @@ -15598,7 +15605,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.20.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.20.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -15677,7 +15684,7 @@ snapshots: dependencies: safe-regex: 2.1.1 - eslint-plugin-turbo@2.5.5(eslint@8.57.1)(turbo@2.3.3): + eslint-plugin-turbo@2.5.6(eslint@8.57.1)(turbo@2.3.3): dependencies: dotenv: 16.0.3 eslint: 8.57.1 @@ -16696,6 +16703,10 @@ snapshots: i18next-fs-backend@2.6.0: {} + i18next-resources-to-backend@1.2.1: + dependencies: + '@babel/runtime': 7.26.0 + i18next@23.16.8: dependencies: '@babel/runtime': 7.26.0 @@ -20461,7 +20472,7 @@ snapshots: type-fest: 2.19.0 unique-string: 3.0.0 - terser-webpack-plugin@5.3.11(webpack@5.92.1): + terser-webpack-plugin@5.3.11(webpack@5.92.1(webpack-cli@5.1.4)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 @@ -20802,7 +20813,7 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-loader@9.5.2(typescript@5.5.3)(webpack@5.92.1): + ts-loader@9.5.2(typescript@5.5.3)(webpack@5.92.1(webpack-cli@5.1.4)): dependencies: chalk: 4.1.2 enhanced-resolve: 5.18.0 @@ -21272,9 +21283,9 @@ snapshots: webpack-cli@5.1.4(webpack@5.92.1): dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.92.1) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.92.1) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack@5.92.1) + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack@5.92.1))(webpack@5.92.1(webpack-cli@5.1.4)) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack@5.92.1))(webpack@5.92.1(webpack-cli@5.1.4)) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack@5.92.1))(webpack@5.92.1(webpack-cli@5.1.4)) colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.6 @@ -21330,7 +21341,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.11(webpack@5.92.1) + terser-webpack-plugin: 5.3.11(webpack@5.92.1(webpack-cli@5.1.4)) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: -- GitLab From 5e699cf51f3bd59880289dde322e8ce0d9afee0d Mon Sep 17 00:00:00 2001 From: Efe Date: Tue, 16 Sep 2025 10:50:58 +0200 Subject: [PATCH 02/70] Create app route folders --- apps/blog/app/[param]/[p2]/[permlink]/.gitkeep | 0 apps/blog/app/[param]/communities/.gitkeep | 0 apps/blog/app/[param]/feed/.gitkeep | 0 apps/blog/app/[param]/lists/.gitkeep | 0 apps/blog/app/api/auth/.gitkeep | 0 apps/blog/app/api/oidc/.gitkeep | 0 apps/blog/app/api/search/.gitkeep | 0 apps/blog/app/api/users/.gitkeep | 0 apps/blog/app/created/.gitkeep | 0 apps/blog/app/faq/.gitkeep | 0 apps/blog/app/hot/.gitkeep | 0 apps/blog/app/muted/.gitkeep | 0 apps/blog/app/payout/.gitkeep | 0 apps/blog/app/payout_comments/.gitkeep | 0 apps/blog/app/privacy/.gitkeep | 0 apps/blog/app/roles/.gitkeep | 0 apps/blog/app/submit/.gitkeep | 0 apps/blog/app/tos/.gitkeep | 0 apps/blog/app/trending/.gitkeep | 0 apps/blog/app/welcome/.gitkeep | 0 20 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/blog/app/[param]/[p2]/[permlink]/.gitkeep create mode 100644 apps/blog/app/[param]/communities/.gitkeep create mode 100644 apps/blog/app/[param]/feed/.gitkeep create mode 100644 apps/blog/app/[param]/lists/.gitkeep create mode 100644 apps/blog/app/api/auth/.gitkeep create mode 100644 apps/blog/app/api/oidc/.gitkeep create mode 100644 apps/blog/app/api/search/.gitkeep create mode 100644 apps/blog/app/api/users/.gitkeep create mode 100644 apps/blog/app/created/.gitkeep create mode 100644 apps/blog/app/faq/.gitkeep create mode 100644 apps/blog/app/hot/.gitkeep create mode 100644 apps/blog/app/muted/.gitkeep create mode 100644 apps/blog/app/payout/.gitkeep create mode 100644 apps/blog/app/payout_comments/.gitkeep create mode 100644 apps/blog/app/privacy/.gitkeep create mode 100644 apps/blog/app/roles/.gitkeep create mode 100644 apps/blog/app/submit/.gitkeep create mode 100644 apps/blog/app/tos/.gitkeep create mode 100644 apps/blog/app/trending/.gitkeep create mode 100644 apps/blog/app/welcome/.gitkeep diff --git a/apps/blog/app/[param]/[p2]/[permlink]/.gitkeep b/apps/blog/app/[param]/[p2]/[permlink]/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/[param]/communities/.gitkeep b/apps/blog/app/[param]/communities/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/[param]/feed/.gitkeep b/apps/blog/app/[param]/feed/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/[param]/lists/.gitkeep b/apps/blog/app/[param]/lists/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/api/auth/.gitkeep b/apps/blog/app/api/auth/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/api/oidc/.gitkeep b/apps/blog/app/api/oidc/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/api/search/.gitkeep b/apps/blog/app/api/search/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/api/users/.gitkeep b/apps/blog/app/api/users/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/created/.gitkeep b/apps/blog/app/created/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/faq/.gitkeep b/apps/blog/app/faq/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/hot/.gitkeep b/apps/blog/app/hot/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/muted/.gitkeep b/apps/blog/app/muted/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/payout/.gitkeep b/apps/blog/app/payout/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/payout_comments/.gitkeep b/apps/blog/app/payout_comments/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/privacy/.gitkeep b/apps/blog/app/privacy/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/roles/.gitkeep b/apps/blog/app/roles/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/submit/.gitkeep b/apps/blog/app/submit/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/tos/.gitkeep b/apps/blog/app/tos/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/trending/.gitkeep b/apps/blog/app/trending/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/welcome/.gitkeep b/apps/blog/app/welcome/.gitkeep new file mode 100644 index 000000000..e69de29bb -- GitLab From 162888b7c7602ebc02ec0226cf87f8fb5d20007e Mon Sep 17 00:00:00 2001 From: Efe Date: Tue, 16 Sep 2025 10:56:43 +0200 Subject: [PATCH 03/70] Add more routes --- apps/blog/app/communities/.gitkeep | 0 apps/blog/app/interaction/.gitkeep | 0 apps/blog/app/page.tsx | 6 ++++++ apps/blog/app/search/.gitkeep | 0 4 files changed, 6 insertions(+) create mode 100644 apps/blog/app/communities/.gitkeep create mode 100644 apps/blog/app/interaction/.gitkeep create mode 100644 apps/blog/app/page.tsx create mode 100644 apps/blog/app/search/.gitkeep diff --git a/apps/blog/app/communities/.gitkeep b/apps/blog/app/communities/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/interaction/.gitkeep b/apps/blog/app/interaction/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/blog/app/page.tsx b/apps/blog/app/page.tsx new file mode 100644 index 000000000..d8d140b86 --- /dev/null +++ b/apps/blog/app/page.tsx @@ -0,0 +1,6 @@ +'use client'; + +const Page = () => { + return
Hive blog app router main page
; +}; +export default Page; diff --git a/apps/blog/app/search/.gitkeep b/apps/blog/app/search/.gitkeep new file mode 100644 index 000000000..e69de29bb -- GitLab From cecb59eef416f5c9a4bea0bcdf0e2087113b8fc5 Mon Sep 17 00:00:00 2001 From: Efe Date: Wed, 17 Sep 2025 14:09:53 +0200 Subject: [PATCH 04/70] Start simple layout --- apps/blog/app/layout.tsx | 43 ++++++++----------- apps/blog/app/page.tsx | 14 +++--- apps/blog/app/trending/.gitkeep | 0 apps/blog/app/trending/page.tsx | 17 ++++++++ apps/blog/pages/{_app.tsx => X_app.tsx} | 0 .../pages/{_document.tsx => X_document.tsx} | 0 apps/blog/pages/{index.tsx => Xindex.tsx} | 0 7 files changed, 42 insertions(+), 32 deletions(-) delete mode 100644 apps/blog/app/trending/.gitkeep create mode 100644 apps/blog/app/trending/page.tsx rename apps/blog/pages/{_app.tsx => X_app.tsx} (100%) rename apps/blog/pages/{_document.tsx => X_document.tsx} (100%) rename apps/blog/pages/{index.tsx => Xindex.tsx} (100%) diff --git a/apps/blog/app/layout.tsx b/apps/blog/app/layout.tsx index b7cafd7f5..5507da109 100644 --- a/apps/blog/app/layout.tsx +++ b/apps/blog/app/layout.tsx @@ -1,36 +1,27 @@ -'use client'; - -import { Providers } from './providers'; import '@hive/tailwindcss-config/globals.css'; -import Head from 'next/head'; -import { Toaster } from '@ui/components/toaster'; -import { useTheme } from 'next-themes'; -import { ModalContainer } from '@smart-signer/components/modal-container'; -import { TailwindIndicator } from '../components/tailwind-indicator'; import { ReactNode } from 'react'; +import { Metadata } from 'next'; -export default function RootLayout({ children }: { children: ReactNode }) { - const { resolvedTheme } = useTheme(); +export const metadata: Metadata = { + title: 'Hive Blog', + description: 'Hive blog application', +}; +export default function RootLayout({ children }: { children: ReactNode }) { return ( - - - - + -
-
- - <> - {children} - - - - - -
+
+
+
+

Hive Blog

+
+
+
+ {children} +
); -} +} \ No newline at end of file diff --git a/apps/blog/app/page.tsx b/apps/blog/app/page.tsx index d8d140b86..cd34d82be 100644 --- a/apps/blog/app/page.tsx +++ b/apps/blog/app/page.tsx @@ -1,6 +1,8 @@ -'use client'; - -const Page = () => { - return
Hive blog app router main page
; -}; -export default Page; +export default function HomePage() { + return ( +
+

Welcome to Hive Blog

+

This is a basic layout test.

+
+ ); +} \ No newline at end of file diff --git a/apps/blog/app/trending/.gitkeep b/apps/blog/app/trending/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/blog/app/trending/page.tsx b/apps/blog/app/trending/page.tsx new file mode 100644 index 000000000..111144502 --- /dev/null +++ b/apps/blog/app/trending/page.tsx @@ -0,0 +1,17 @@ +export default function TrendingPage() { + return ( +
+

Trending Posts

+
+
+

Sample Post 1

+

This is a sample trending post content.

+
+
+

Sample Post 2

+

This is another sample trending post content.

+
+
+
+ ); +} diff --git a/apps/blog/pages/_app.tsx b/apps/blog/pages/X_app.tsx similarity index 100% rename from apps/blog/pages/_app.tsx rename to apps/blog/pages/X_app.tsx diff --git a/apps/blog/pages/_document.tsx b/apps/blog/pages/X_document.tsx similarity index 100% rename from apps/blog/pages/_document.tsx rename to apps/blog/pages/X_document.tsx diff --git a/apps/blog/pages/index.tsx b/apps/blog/pages/Xindex.tsx similarity index 100% rename from apps/blog/pages/index.tsx rename to apps/blog/pages/Xindex.tsx -- GitLab From 0c3cec3163eaebc7f4f2ccbaada44db5d9734a3a Mon Sep 17 00:00:00 2001 From: Efe Date: Wed, 17 Sep 2025 14:15:02 +0200 Subject: [PATCH 05/70] move document and app to main layout --- apps/blog/app/layout.tsx | 35 +++++++++++++++++++++++++++++------ apps/blog/app/providers.tsx | 21 --------------------- 2 files changed, 29 insertions(+), 27 deletions(-) delete mode 100644 apps/blog/app/providers.tsx diff --git a/apps/blog/app/layout.tsx b/apps/blog/app/layout.tsx index 5507da109..a2a66aa20 100644 --- a/apps/blog/app/layout.tsx +++ b/apps/blog/app/layout.tsx @@ -1,10 +1,34 @@ import '@hive/tailwindcss-config/globals.css'; import { ReactNode } from 'react'; import { Metadata } from 'next'; +import Script from 'next/script'; + +// Get basePath from build-time environment +const basePath = process.env.NEXT_PUBLIC_BASE_PATH || ''; + +const SITE_DESC = + 'Communities without borders. A social network owned and operated by its users, powered by Hive.'; export const metadata: Metadata = { - title: 'Hive Blog', - description: 'Hive blog application', + title: 'Hive', + description: SITE_DESC, + icons: { + icon: '/favicon.ico' + }, + openGraph: { + type: 'website', + siteName: 'Hive', + title: 'Hive', + description: SITE_DESC, + images: ['https://hive.blog/images/hive-blog-share.png'] + }, + twitter: { + card: 'summary', + site: '@hiveblocks', + title: '#Hive.io', + description: SITE_DESC, + images: ['https://hive.blog/images/hive-blog-twshare.png'] + } }; export default function RootLayout({ children }: { children: ReactNode }) { @@ -17,11 +41,10 @@ export default function RootLayout({ children }: { children: ReactNode }) {

Hive Blog

-
- {children} -
+
{children}
+