chore: scaffold twitter lite

This commit is contained in:
2026-07-13 09:41:34 +09:00
parent 245d8d743f
commit c4382c1669
17 changed files with 3459 additions and 0 deletions
+68
View File
@@ -0,0 +1,68 @@
/* eslint-disable */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// This file was automatically generated by TanStack Router.
// You should NOT make any changes in this file as it will be overwritten.
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import { Route as rootRouteImport } from './routes/__root'
import { Route as IndexRouteImport } from './routes/index'
const IndexRoute = IndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => rootRouteImport,
} as any)
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: '/'
fileRoutesByTo: FileRoutesByTo
to: '/'
id: '__root__' | '/'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
}
declare module '@tanstack/react-router' {
interface FileRoutesByPath {
'/': {
id: '/'
path: '/'
fullPath: '/'
preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport
}
}
}
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
}
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)
._addFileTypes<FileRouteTypes>()
import type { getRouter } from './router.tsx'
import type { createStart } from '@tanstack/react-start'
declare module '@tanstack/react-start' {
interface Register {
ssr: true
router: Awaited<ReturnType<typeof getRouter>>
}
}
+27
View File
@@ -0,0 +1,27 @@
import { QueryClient } from '@tanstack/react-query'
import { createRouter } from '@tanstack/react-router'
import { setupRouterSsrQueryIntegration } from '@tanstack/react-router-ssr-query'
import { routeTree } from './routeTree.gen'
export function getRouter() {
const queryClient = new QueryClient({
defaultOptions: {
queries: { retry: false, staleTime: 0, gcTime: 0 },
},
})
const router = createRouter({
routeTree,
context: { queryClient },
scrollRestoration: true,
defaultPreload: false,
})
setupRouterSsrQueryIntegration({ router, queryClient })
return router
}
declare module '@tanstack/react-router' {
interface Register {
router: ReturnType<typeof getRouter>
}
}
+38
View File
@@ -0,0 +1,38 @@
import type { QueryClient } from '@tanstack/react-query'
import {
createRootRouteWithContext,
HeadContent,
Scripts,
} from '@tanstack/react-router'
import appCss from '../styles.css?url'
type RouterContext = { queryClient: QueryClient }
export const Route = createRootRouteWithContext<RouterContext>()({
head: () => ({
meta: [
{ charSet: 'utf-8' },
{
name: 'viewport',
content: 'width=device-width, initial-scale=1',
},
{ title: 'Twitter Lite' },
],
links: [{ rel: 'stylesheet', href: appCss }],
}),
shellComponent: RootDocument,
})
function RootDocument({ children }: { children: React.ReactNode }) {
return (
<html lang="ja">
<head>
<HeadContent />
</head>
<body>
{children}
<Scripts />
</body>
</html>
)
}
+12
View File
@@ -0,0 +1,12 @@
import { render, screen } from '@testing-library/react'
import { describe, expect, it } from 'vitest'
import { Home } from './index'
describe('Home', () => {
it('starts without ambient post content', () => {
render(<Home />)
expect(screen.getByText('目的を決めてから開く')).toBeInTheDocument()
expect(screen.queryByRole('article')).not.toBeInTheDocument()
})
})
+13
View File
@@ -0,0 +1,13 @@
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/')({ component: Home })
export function Home() {
return (
<main className="landing">
<p className="brand">TWITTER LITE</p>
<h1>目的を決めてから開く</h1>
<p>ユーザー名か検索語を入力するまで、投稿は表示しません。</p>
</main>
)
}
+35
View File
@@ -0,0 +1,35 @@
:root {
color: #1e3238;
background: #dfe7e9;
font-family: Inter, "Noto Sans JP", ui-sans-serif, system-ui, sans-serif;
}
* {
box-sizing: border-box;
}
body {
min-width: 320px;
min-height: 100vh;
margin: 0;
}
button,
input {
font: inherit;
}
.landing {
width: min(42rem, calc(100% - 2rem));
margin: 15vh auto;
padding: 2rem;
border: 1px solid #c1cfd2;
border-radius: 1rem;
background: #f8faf9;
}
.brand {
color: #70858a;
font-size: 0.7rem;
letter-spacing: 0.2em;
}