Initial commit (fresh repo)
This commit is contained in:
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Nuxt dev/build outputs
|
||||
.output
|
||||
.data
|
||||
.nuxt
|
||||
.nitro
|
||||
.cache
|
||||
dist
|
||||
|
||||
# Node dependencies
|
||||
node_modules
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.fleet
|
||||
.idea
|
||||
|
||||
# Local env files
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
30
AGENTS.md
Normal file
30
AGENTS.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Repository Guidelines
|
||||
|
||||
## Project Structure & Module Organization
|
||||
- `app/app.vue` hosts the root Nuxt view; keep it lean and delegate features to components under a future `components/` directory.
|
||||
- `public/` holds static assets served as-is.
|
||||
- `nuxt.config.ts` centralizes Nuxt settings; add modules and runtime config here instead of inside components.
|
||||
- `package.json` scripts are the source of truth for commands; avoid ad-hoc shell scripts.
|
||||
|
||||
## Build, Test, and Development Commands
|
||||
- `npm run dev` — start Nuxt dev server at `http://localhost:3000` with HMR.
|
||||
- `npm run build` — production build; ensure this passes before merging.
|
||||
- `npm run preview` — serve the production build locally to validate routes and assets.
|
||||
- `npm run generate` — create a static export for static hosting targets.
|
||||
- Install dependencies with `npm install` (npm lockfile is committed).
|
||||
|
||||
## Coding Style & Naming Conventions
|
||||
- Language: Vue 3 with Nuxt 4; prefer `<script setup lang="ts">` and the Composition API.
|
||||
- Formatting: 2-space indentation; run a formatter (e.g., `npx prettier`) before pushing; keep templates tidy and avoid inline styles when practical.
|
||||
- Naming: PascalCase for components (`HeroSection.vue`), camelCase for composables/utilities (`useFeatureFlag`), kebab-case for file names except Vue components.
|
||||
- Imports: use Nuxt aliases for clarity (e.g., `~/components/Button.vue`) instead of long relative paths.
|
||||
|
||||
## Testing Guidelines
|
||||
- No automated tests are configured yet; add coverage with new features rather than deferring.
|
||||
- If you add tests, co-locate unit specs with components (`Button.spec.ts`) and keep integration/E2E flows under `tests/`.
|
||||
- Always run `npm run build` and do a quick browser smoke test of impacted routes before opening a PR.
|
||||
|
||||
## Commit & Pull Request Guidelines
|
||||
- Commits: imperative mood (`Add hero CTA copy`) and scoped to a single concern; avoid mixing refactors with feature work.
|
||||
- Pull Requests: include a concise summary, screenshots or recordings for UI changes, reproduction steps for fixes, and any follow-up items.
|
||||
- Link issues when relevant and call out breaking changes explicitly in the description.
|
||||
78
README.md
Normal file
78
README.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Nuxt Minimal Starter
|
||||
|
||||
Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||
|
||||
## Setup
|
||||
|
||||
Make sure to install dependencies:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm install
|
||||
|
||||
# pnpm
|
||||
pnpm install
|
||||
|
||||
# yarn
|
||||
yarn install
|
||||
|
||||
# bun
|
||||
bun install
|
||||
```
|
||||
|
||||
## Development Server
|
||||
|
||||
Start the development server on `http://localhost:3000`:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run dev
|
||||
|
||||
# pnpm
|
||||
pnpm dev
|
||||
|
||||
# yarn
|
||||
yarn dev
|
||||
|
||||
# bun
|
||||
bun run dev
|
||||
```
|
||||
|
||||
## Production
|
||||
|
||||
Build the application for production:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run build
|
||||
|
||||
# pnpm
|
||||
pnpm build
|
||||
|
||||
# yarn
|
||||
yarn build
|
||||
|
||||
# bun
|
||||
bun run build
|
||||
```
|
||||
|
||||
Locally preview production build:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run preview
|
||||
|
||||
# pnpm
|
||||
pnpm preview
|
||||
|
||||
# yarn
|
||||
yarn preview
|
||||
|
||||
# bun
|
||||
bun run preview
|
||||
```
|
||||
|
||||
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
||||
|
||||
Для production: установи переменную окружения:
|
||||
NUXT_PUBLIC_API_BASE=https://your-api-domain.com
|
||||
5
app/app.vue
Normal file
5
app/app.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<NuxtLayout>
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
</template>
|
||||
70
app/assets/css/tailwind.css
Normal file
70
app/assets/css/tailwind.css
Normal file
@@ -0,0 +1,70 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--font-heading: 'Space Grotesk', 'Manrope', system-ui, -apple-system, sans-serif;
|
||||
--font-body: 'Manrope', system-ui, -apple-system, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-slate-50 text-slate-900 font-body antialiased;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
.font-heading {
|
||||
font-family: var(--font-heading);
|
||||
}
|
||||
.font-body {
|
||||
font-family: var(--font-body);
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.shadow-card {
|
||||
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.12);
|
||||
}
|
||||
.shadow-floating {
|
||||
box-shadow: 0 14px 42px rgba(59, 130, 246, 0.18);
|
||||
}
|
||||
}
|
||||
|
||||
.gradient-ring {
|
||||
background: radial-gradient(circle at 20% 20%, rgba(59, 130, 246, 0.12), transparent 35%),
|
||||
radial-gradient(circle at 80% 10%, rgba(14, 165, 233, 0.12), transparent 32%),
|
||||
radial-gradient(circle at 50% 80%, rgba(99, 102, 241, 0.1), transparent 30%);
|
||||
}
|
||||
|
||||
.section-shell {
|
||||
@apply relative overflow-hidden rounded-3xl border border-slate-200 bg-white/95 backdrop-blur shadow-card;
|
||||
}
|
||||
|
||||
.card-surface {
|
||||
@apply rounded-2xl border border-slate-200 bg-white p-6 shadow-card transition duration-300;
|
||||
}
|
||||
|
||||
.card-surface:hover {
|
||||
transform: translateY(-0.25rem);
|
||||
box-shadow: 0 12px 34px rgba(59, 130, 246, 0.16);
|
||||
}
|
||||
|
||||
.badge {
|
||||
@apply inline-flex items-center gap-2 rounded-full bg-blue-50 px-3 py-1 text-xs font-semibold uppercase tracking-wide text-blue-700;
|
||||
}
|
||||
|
||||
.fade-up {
|
||||
opacity: 0;
|
||||
animation: fade-up 0.9s ease forwards;
|
||||
}
|
||||
|
||||
@keyframes fade-up {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
35
app/components/CTA.vue
Normal file
35
app/components/CTA.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<script setup lang="ts">
|
||||
const config = useRuntimeConfig()
|
||||
|
||||
function trackBot() {
|
||||
fetch(`${config.public.apiBase}/api/track/bot/`, { method: 'POST' }).catch(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="py-16 sm:py-20 lg:py-24">
|
||||
<div class="container mx-auto max-w-5xl px-4">
|
||||
<div class="section-shell p-[1px] bg-gradient-to-r from-blue-100 via-white to-indigo-100">
|
||||
<div class="rounded-3xl bg-white px-8 py-10 text-center shadow-card sm:px-12 sm:py-14">
|
||||
<p class="badge mx-auto">Готов к старту</p>
|
||||
<h2 class="mt-4 font-heading text-3xl sm:text-4xl">Начни изучать язык сегодня</h2>
|
||||
<p class="mt-3 text-lg text-slate-700 sm:text-xl">Учись в удобном формате с помощью AI</p>
|
||||
<div class="mt-6 flex flex-wrap items-center justify-center gap-4">
|
||||
<a
|
||||
class="inline-flex items-center gap-2 rounded-full bg-blue-600 px-6 py-3 text-base font-semibold text-white shadow-floating transition hover:-translate-y-1 hover:bg-blue-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"
|
||||
href="https://t.me/animeenigma_language_bot"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
@click="trackBot"
|
||||
>
|
||||
Открыть Telegram-бота
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M5 12h14m0 0-5-5m5 5-5 5" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
52
app/components/Dialogs.vue
Normal file
52
app/components/Dialogs.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<section class="py-14 sm:py-16 lg:py-20">
|
||||
<div class="container mx-auto max-w-6xl px-4">
|
||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
|
||||
<div>
|
||||
<p class="badge">Диалоговая практика</p>
|
||||
<h2 class="font-heading text-2xl sm:text-3xl lg:text-4xl">6 сценариев с AI-собеседником</h2>
|
||||
<p class="mt-2 text-slate-600">AI ведёт разговор, исправляет ошибки, даёт подсказки и перевод сообщений.</p>
|
||||
</div>
|
||||
<div class="text-sm text-slate-500">Карточки анимируются при наведении.</div>
|
||||
</div>
|
||||
<div class="mt-8 grid gap-5 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<div
|
||||
v-for="(item, idx) in dialogs"
|
||||
:key="item.title"
|
||||
class="card-surface fade-up"
|
||||
:style="{ animationDelay: `${idx * 0.07}s` }"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="flex h-10 w-10 items-center justify-center rounded-full bg-blue-50 text-lg">{{ item.emoji }}</div>
|
||||
<div>
|
||||
<p class="text-sm text-slate-500">{{ item.label }}</p>
|
||||
<h3 class="font-heading text-lg">{{ item.title }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-blue-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
</div>
|
||||
<p class="mt-3 text-sm text-slate-600">{{ item.desc }}</p>
|
||||
<div class="mt-4 flex flex-wrap gap-2 text-xs text-slate-700">
|
||||
<span class="rounded-full bg-blue-50 px-3 py-1 text-blue-800">Исправление ошибок</span>
|
||||
<span class="rounded-full bg-indigo-50 px-3 py-1 text-indigo-800">Подсказки</span>
|
||||
<span class="rounded-full bg-emerald-50 px-3 py-1 text-emerald-800">Перевод</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const dialogs = [
|
||||
{ emoji: '🍣', label: 'Ресторан', title: 'Бронь и заказ', desc: 'Практикуй заказ блюд, замену ингредиентов и small talk с официантом.' },
|
||||
{ emoji: '🛍️', label: 'Магазин', title: 'Покупки и возврат', desc: 'Спрашивай про размеры, оформляй возвраты и уточняй акции.' },
|
||||
{ emoji: '✈️', label: 'Путешествия', title: 'Аэропорт и отель', desc: 'Check-in, паспортный контроль, просьбы на стойке регистрации.' },
|
||||
{ emoji: '💼', label: 'Работа', title: 'Созвоны и письма', desc: 'Стэнд-апы, уточнение задач, переговоры с заказчиком.' },
|
||||
{ emoji: '⚕️', label: 'Врач', title: 'Запись и симптомы', desc: 'Опиши симптомы, получи рекомендации и отработай мед. лексику.' },
|
||||
{ emoji: '💬', label: 'Свободный диалог', title: 'Топики по запросу', desc: 'AI поддержит разговор на любую тему и подскажет формулировки.' }
|
||||
]
|
||||
</script>
|
||||
39
app/components/Features.vue
Normal file
39
app/components/Features.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<section class="py-14 sm:py-16 lg:py-20">
|
||||
<div class="container mx-auto max-w-6xl px-4">
|
||||
<div class="mb-10 flex flex-col gap-3 sm:mb-12 sm:flex-row sm:items-end sm:justify-between">
|
||||
<div>
|
||||
<p class="badge">Почему это удобно</p>
|
||||
<h2 class="font-heading text-2xl sm:text-3xl lg:text-4xl">Преимущества бота</h2>
|
||||
<p class="mt-2 text-slate-600">AI помогает учиться в любом чате Telegram, без лишних приложений.</p>
|
||||
</div>
|
||||
<div class="text-sm text-slate-500">Карточки реагируют на hover и подчеркивают ключевые функции.</div>
|
||||
</div>
|
||||
<div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<div
|
||||
v-for="(item, idx) in items"
|
||||
:key="item.title"
|
||||
class="card-surface fade-up"
|
||||
:style="{ animationDelay: `${idx * 0.06}s` }"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="flex h-11 w-11 items-center justify-center rounded-full bg-blue-50 text-lg">{{ item.emoji }}</div>
|
||||
<h3 class="font-heading text-lg">{{ item.title }}</h3>
|
||||
</div>
|
||||
<p class="mt-3 text-sm text-slate-600">{{ item.desc }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const items = [
|
||||
{ emoji: '🤖', title: 'AI внутри', desc: 'Умная проверка ответов, генерация заданий и диалоговая практика на лету.' },
|
||||
{ emoji: '📱', title: 'Всегда под рукой', desc: 'Учись прямо в Telegram на телефоне или десктопе — ничего не нужно устанавливать.' },
|
||||
{ emoji: '🎯', title: 'Персональный подход', desc: 'Задания и диалоги адаптируются под уровень A1–C2 и N5–N1.' },
|
||||
{ emoji: '📚', title: 'Контекст важен', desc: 'Слова сохраняются вместе с примерами, чтобы запоминать в реальных ситуациях.' },
|
||||
{ emoji: '🆓', title: 'Бесплатно', desc: 'Основной функционал доступен без оплаты — достаточно открыть бота.' },
|
||||
{ emoji: '⚡', title: 'Быстрый старт', desc: 'Первые задания за минуту: бот сразу подбирает нужный сценарий.' }
|
||||
]
|
||||
</script>
|
||||
37
app/components/Footer.vue
Normal file
37
app/components/Footer.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
const config = useRuntimeConfig()
|
||||
|
||||
function trackBot() {
|
||||
fetch(`${config.public.apiBase}/api/track/bot/`, { method: 'POST' }).catch(() => {})
|
||||
}
|
||||
|
||||
function trackChannel() {
|
||||
fetch(`${config.public.apiBase}/api/track/channel/`, { method: 'POST' }).catch(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<footer class="border-t border-slate-200 bg-white py-10 text-slate-700">
|
||||
<div class="container mx-auto max-w-6xl px-4">
|
||||
<div class="flex flex-col gap-6 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center gap-2 text-lg font-heading text-slate-900">
|
||||
<span class="flex h-9 w-9 items-center justify-center rounded-full bg-blue-600 text-white font-bold">AE</span>
|
||||
Anime Enigma Language Bot
|
||||
</div>
|
||||
<p class="text-sm text-slate-600">AI-помощник для английского A1–C2 и японского N5–N1.</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-4 text-sm">
|
||||
<a class="inline-flex items-center gap-2 hover:text-blue-700" href="https://t.me/animeenigma_language_bot" target="_blank" rel="noreferrer" @click="trackBot">
|
||||
<span class="h-2 w-2 rounded-full bg-emerald-500"></span>
|
||||
@animeenigma_language_bot
|
||||
</a>
|
||||
<a class="inline-flex items-center gap-2 hover:text-blue-700" href="https://t.me/animeenigmalanguage" target="_blank" rel="noreferrer" @click="trackChannel">
|
||||
<span class="h-2 w-2 rounded-full bg-cyan-500"></span>
|
||||
@animeenigmalanguage
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</template>
|
||||
109
app/components/Hero.vue
Normal file
109
app/components/Hero.vue
Normal file
@@ -0,0 +1,109 @@
|
||||
<script setup lang="ts">
|
||||
const config = useRuntimeConfig()
|
||||
|
||||
function trackBot() {
|
||||
fetch(`${config.public.apiBase}/api/track/bot/`, { method: 'POST' }).catch(() => {})
|
||||
}
|
||||
|
||||
function trackChannel() {
|
||||
fetch(`${config.public.apiBase}/api/track/channel/`, { method: 'POST' }).catch(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="relative overflow-hidden py-16 sm:py-20 lg:py-24">
|
||||
<div class="container mx-auto max-w-6xl px-4">
|
||||
<div class="section-shell grid items-center gap-12 p-8 sm:p-10 lg:grid-cols-2">
|
||||
<div class="space-y-6 fade-up">
|
||||
<div class="badge">AI + Telegram</div>
|
||||
<h1 class="font-heading text-3xl leading-tight sm:text-4xl lg:text-5xl">
|
||||
Telegram-бот для изучения английского и японского с AI
|
||||
</h1>
|
||||
<p class="text-lg text-slate-600 sm:text-xl">
|
||||
Пополняй словарь, выполняй задания, практикуй диалоги — всё в одном боте. Искусственный интеллект адаптируется
|
||||
под твой уровень.
|
||||
</p>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<a
|
||||
class="inline-flex items-center gap-2 rounded-full bg-blue-600 px-6 py-3 text-base font-semibold text-white shadow-md transition hover:-translate-y-0.5 hover:bg-blue-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"
|
||||
href="https://t.me/animeenigma_language_bot"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
@click="trackBot"
|
||||
>
|
||||
Открыть бота
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M5 12h14m0 0-5-5m5 5-5 5" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
class="inline-flex items-center gap-2 rounded-full border border-slate-300 bg-white px-6 py-3 text-base font-semibold text-slate-900 shadow-sm transition hover:-translate-y-0.5 hover:bg-slate-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"
|
||||
href="https://t.me/animeenigmalanguage"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
@click="trackChannel"
|
||||
>
|
||||
Telegram-канал
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M14.25 9.75 16.5 12l-2.25 2.25m-3-4.5L9 12l2.25 2.25" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-3 text-sm text-slate-500">
|
||||
<span class="inline-flex items-center gap-2 rounded-full bg-blue-50 px-3 py-1 text-blue-800">
|
||||
<span class="h-2 w-2 rounded-full bg-green-500"></span>
|
||||
Уровни A1–C2 и N5–N1
|
||||
</span>
|
||||
<span class="inline-flex items-center gap-2 rounded-full bg-indigo-50 px-3 py-1 text-indigo-800">
|
||||
<span class="h-2 w-2 rounded-full bg-cyan-500"></span>
|
||||
Быстрый старт без установки
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative isolate">
|
||||
<div class="absolute -left-10 -top-14 h-64 w-64 rounded-full bg-blue-200 opacity-60 blur-3xl"></div>
|
||||
<div class="absolute -right-16 bottom-6 h-52 w-52 rounded-full bg-gradient-to-br from-indigo-200 to-blue-100 blur-3xl"></div>
|
||||
<div class="relative grid gap-4">
|
||||
<div class="card-surface fade-up">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-sm text-slate-500">Уровень</p>
|
||||
<p class="text-2xl font-semibold">CEFR B2 · JLPT N3</p>
|
||||
</div>
|
||||
<div class="flex h-12 w-12 items-center justify-center rounded-full bg-blue-50 text-blue-600">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 6v6l4 2" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 h-2 w-full rounded-full bg-slate-100">
|
||||
<div class="h-2 w-3/4 rounded-full bg-blue-600"></div>
|
||||
</div>
|
||||
<p class="mt-3 text-sm text-slate-600">AI подбирает задания под оба языка одновременно.</p>
|
||||
</div>
|
||||
<div class="card-surface fade-up" style="animation-delay: 0.15s">
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="flex h-12 w-12 items-center justify-center rounded-full bg-indigo-50 text-indigo-600">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 11.25c1.864 0 3.375-1.511 3.375-3.375S13.864 4.5 12 4.5s-3.375 1.511-3.375 3.375S10.136 11.25 12 11.25Z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M5.25 20.25a6.75 6.75 0 1 1 13.5 0" />
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm text-slate-500">Диалоги</p>
|
||||
<p class="text-lg font-semibold text-slate-900">AI-собеседник и мгновенные подсказки</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 grid grid-cols-3 gap-2 text-xs text-slate-700">
|
||||
<span class="rounded-full bg-blue-50 px-3 py-2 text-center text-blue-800">Ресторан</span>
|
||||
<span class="rounded-full bg-indigo-50 px-3 py-2 text-center text-indigo-800">Путешествия</span>
|
||||
<span class="rounded-full bg-slate-100 px-3 py-2 text-center text-slate-800">Работа</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
48
app/components/Languages.vue
Normal file
48
app/components/Languages.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<section class="py-14 sm:py-16 lg:py-20">
|
||||
<div class="container mx-auto max-w-6xl px-4">
|
||||
<div class="section-shell space-y-8 p-8 sm:p-10">
|
||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
|
||||
<div>
|
||||
<p class="badge">Поддерживаемые языки</p>
|
||||
<h2 class="font-heading text-2xl sm:text-3xl lg:text-4xl">Английский и японский</h2>
|
||||
<p class="mt-2 text-slate-600">Уровни CEFR A1–C2 и JLPT N5–N1, интерфейс на русском, английском и японском.</p>
|
||||
</div>
|
||||
<div class="rounded-full border border-slate-200 bg-slate-50 px-4 py-2 text-sm text-slate-700">Интерфейс: RU · EN · JP</div>
|
||||
</div>
|
||||
<div class="grid gap-6 md:grid-cols-2">
|
||||
<div class="card-surface fade-up">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="text-2xl">🇬🇧</span>
|
||||
<div>
|
||||
<p class="text-sm uppercase tracking-wide text-slate-500">English</p>
|
||||
<h3 class="font-heading text-xl">CEFR A1–C2</h3>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-3 text-sm text-slate-600">Диалоги, задания и словарь с транскрипциями, устойчивыми выражениями и примерами.</p>
|
||||
<div class="mt-4 flex flex-wrap gap-2 text-xs text-slate-700">
|
||||
<span class="rounded-full bg-blue-50 px-3 py-1 text-blue-800">Произношение</span>
|
||||
<span class="rounded-full bg-indigo-50 px-3 py-1 text-indigo-800">Фразовые глаголы</span>
|
||||
<span class="rounded-full bg-amber-50 px-3 py-1 text-amber-800">Бизнес-лексика</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-surface fade-up" style="animation-delay: 0.08s">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="text-2xl">🇯🇵</span>
|
||||
<div>
|
||||
<p class="text-sm uppercase tracking-wide text-slate-500">日本語</p>
|
||||
<h3 class="font-heading text-xl">JLPT N5–N1</h3>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-3 text-sm text-slate-600">Кандзи, чтения, примеры предложений и контекстные подсказки для каждого уровня JLPT.</p>
|
||||
<div class="mt-4 flex flex-wrap gap-2 text-xs text-slate-700">
|
||||
<span class="rounded-full bg-red-50 px-3 py-1 text-red-800">Кандзи + фуриганда</span>
|
||||
<span class="rounded-full bg-blue-50 px-3 py-1 text-blue-800">Грамматика JLPT</span>
|
||||
<span class="rounded-full bg-slate-100 px-3 py-1 text-slate-800">Сленг / 日常会話</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
93
app/components/Progress.vue
Normal file
93
app/components/Progress.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<section class="py-14 sm:py-16 lg:py-20">
|
||||
<div class="container mx-auto max-w-6xl px-4">
|
||||
<div class="section-shell p-8 sm:p-10">
|
||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
|
||||
<div>
|
||||
<p class="badge">Отслеживание прогресса</p>
|
||||
<h2 class="font-heading text-2xl sm:text-3xl lg:text-4xl">Статистика и история повторений</h2>
|
||||
<p class="mt-2 text-slate-600">Следи за ростом словаря, точностью ответов и прогресс-барами по уровням.</p>
|
||||
</div>
|
||||
<div class="text-sm text-slate-500">Данные всегда рядом в боте.</div>
|
||||
</div>
|
||||
<div class="mt-8 grid gap-6 md:grid-cols-2">
|
||||
<div class="card-surface fade-up">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-sm text-slate-500">Статистика слов</p>
|
||||
<h3 class="font-heading text-xl">2 450 слов в словаре</h3>
|
||||
</div>
|
||||
<div class="flex h-12 w-12 items-center justify-center rounded-full bg-blue-50 text-blue-700">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4.5 19.5 9 15l4 4 6-6v6h-15Z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 space-y-3">
|
||||
<div>
|
||||
<div class="flex items-center justify-between text-sm text-slate-600">
|
||||
<span>История повторений</span>
|
||||
<span>+18% за неделю</span>
|
||||
</div>
|
||||
<div class="mt-2 h-2 w-full rounded-full bg-slate-100">
|
||||
<div class="h-2 w-4/5 rounded-full bg-blue-600"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="flex items-center justify-between text-sm text-slate-600">
|
||||
<span>Точность заданий</span>
|
||||
<span>92%</span>
|
||||
</div>
|
||||
<div class="mt-2 h-2 w-full rounded-full bg-slate-100">
|
||||
<div class="h-2 w-11/12 rounded-full bg-emerald-500"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-surface fade-up" style="animation-delay: 0.12s">
|
||||
<p class="text-sm text-slate-500">Прогресс по уровням</p>
|
||||
<h3 class="font-heading text-lg">CEFR и JLPT в одном дашборде</h3>
|
||||
<div class="mt-4 grid grid-cols-2 gap-3 text-sm text-slate-700">
|
||||
<div class="rounded-xl bg-slate-100 p-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<span>CEFR</span>
|
||||
<span class="rounded-full bg-blue-50 px-2 py-1 text-xs text-blue-700">B2</span>
|
||||
</div>
|
||||
<div class="mt-2 h-2 w-full rounded-full bg-slate-200">
|
||||
<div class="h-2 w-[72%] rounded-full bg-blue-600"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded-xl bg-slate-100 p-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<span>JLPT</span>
|
||||
<span class="rounded-full bg-indigo-50 px-2 py-1 text-xs text-indigo-700">N3</span>
|
||||
</div>
|
||||
<div class="mt-2 h-2 w-full rounded-full bg-slate-200">
|
||||
<div class="h-2 w-[64%] rounded-full bg-indigo-500"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded-xl bg-slate-100 p-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<span>Дни подряд</span>
|
||||
<span class="rounded-full bg-green-50 px-2 py-1 text-xs text-green-700">12</span>
|
||||
</div>
|
||||
<div class="mt-2 h-2 w-full rounded-full bg-slate-200">
|
||||
<div class="h-2 w-[90%] rounded-full bg-emerald-500"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded-xl bg-slate-100 p-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<span>Диалоги</span>
|
||||
<span class="rounded-full bg-amber-50 px-2 py-1 text-xs text-amber-700">128</span>
|
||||
</div>
|
||||
<div class="mt-2 h-2 w-full rounded-full bg-slate-200">
|
||||
<div class="h-2 w-[55%] rounded-full bg-cyan-500"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
61
app/components/SmartDictionary.vue
Normal file
61
app/components/SmartDictionary.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<section class="py-14 sm:py-16 lg:py-20">
|
||||
<div class="container mx-auto max-w-6xl px-4">
|
||||
<div class="section-shell p-8 sm:p-10">
|
||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
|
||||
<div>
|
||||
<p class="badge">Умный словарь</p>
|
||||
<h2 class="font-heading text-2xl sm:text-3xl lg:text-4xl">Контекстный словарь с AI</h2>
|
||||
<p class="mt-2 text-slate-600">Переводы, транскрипции, примеры и тематические подборки в одном окне бота.</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 rounded-full border border-slate-200 bg-slate-50 px-4 py-2 text-sm text-slate-700">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 6v12m6-6H6" />
|
||||
</svg>
|
||||
Добавляй слова вручную или импортом
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-8 grid gap-6 lg:grid-cols-3">
|
||||
<div class="card-surface fade-up lg:col-span-2">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-sm text-slate-500">Ручное добавление</p>
|
||||
<h3 class="font-heading text-xl">AI анализирует и дополняет карточку</h3>
|
||||
</div>
|
||||
<div class="flex h-12 w-12 items-center justify-center rounded-full bg-blue-50 text-blue-700">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6 18 18 6m0 0H9m9 0v9" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 grid gap-3 sm:grid-cols-2">
|
||||
<div class="rounded-xl bg-slate-100 p-4 text-sm text-slate-700">Перевод, транскрипция, примеры и синонимы.</div>
|
||||
<div class="rounded-xl bg-slate-100 p-4 text-sm text-slate-700">Несколько значений с контекстами и пояснениями.</div>
|
||||
<div class="rounded-xl bg-slate-100 p-4 text-sm text-slate-700">Тематические подборки по запросу, готовые к повторению.</div>
|
||||
<div class="rounded-xl bg-slate-100 p-4 text-sm text-slate-700">Пагинация словаря для больших списков.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-surface fade-up" style="animation-delay: 0.12s">
|
||||
<p class="text-sm text-slate-500">Импорт текста</p>
|
||||
<h3 class="font-heading text-lg">Извлечение слов из книг и статей</h3>
|
||||
<p class="mt-3 text-sm text-slate-600">Бот анализирует .txt и .md файлы, создаёт карточки с примерами использования.</p>
|
||||
<div class="mt-4 space-y-2 text-sm text-slate-700">
|
||||
<div class="flex items-center gap-2 rounded-lg bg-blue-50 px-3 py-2">
|
||||
<span class="h-2 w-2 rounded-full bg-emerald-500"></span>
|
||||
Импорт .txt / .md файлов
|
||||
</div>
|
||||
<div class="flex items-center gap-2 rounded-lg bg-indigo-50 px-3 py-2">
|
||||
<span class="h-2 w-2 rounded-full bg-cyan-500"></span>
|
||||
Автодобавление в нужные уровни CEFR и JLPT
|
||||
</div>
|
||||
<div class="flex items-center gap-2 rounded-lg bg-amber-50 px-3 py-2">
|
||||
<span class="h-2 w-2 rounded-full bg-violet-500"></span>
|
||||
Сохранение примеров для последующих заданий
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
64
app/components/Tasks.vue
Normal file
64
app/components/Tasks.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<section class="py-14 sm:py-16 lg:py-20">
|
||||
<div class="container mx-auto max-w-6xl px-4">
|
||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
|
||||
<div>
|
||||
<p class="badge">Интерактивные задания</p>
|
||||
<h2 class="font-heading text-2xl sm:text-3xl lg:text-4xl">Практика, которая адаптируется</h2>
|
||||
<p class="mt-2 text-slate-600">AI оценивает ответы, принимает синонимы и подбирает следующую сложность.</p>
|
||||
</div>
|
||||
<div class="text-sm text-slate-500">Переключай режимы: перевод, пропуски, контекст.</div>
|
||||
</div>
|
||||
<div class="mt-8 grid gap-6 lg:grid-cols-3">
|
||||
<div class="card-surface fade-up lg:col-span-2">
|
||||
<div class="flex flex-wrap gap-2 text-xs text-slate-700">
|
||||
<span class="rounded-full bg-blue-50 px-3 py-1 text-blue-800">Перевод слов в обе стороны</span>
|
||||
<span class="rounded-full bg-indigo-50 px-3 py-1 text-indigo-800">Новые слова на основе уровня</span>
|
||||
<span class="rounded-full bg-emerald-50 px-3 py-1 text-emerald-800">Заполнение пропусков</span>
|
||||
<span class="rounded-full bg-amber-50 px-3 py-1 text-amber-800">Перевод по контексту</span>
|
||||
</div>
|
||||
<div class="mt-5 grid gap-3 sm:grid-cols-2">
|
||||
<div class="rounded-2xl bg-slate-100 p-4 text-sm text-slate-700">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="font-semibold">Умная проверка</span>
|
||||
<span class="rounded-full bg-emerald-100 px-3 py-1 text-xs text-emerald-700">Принимает синонимы</span>
|
||||
</div>
|
||||
<p class="mt-2 text-slate-600">AI сравнивает смысл ответа, а не только точное совпадение.</p>
|
||||
</div>
|
||||
<div class="rounded-2xl bg-slate-100 p-4 text-sm text-slate-700">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="font-semibold">Примеры после ответа</span>
|
||||
<span class="rounded-full bg-cyan-100 px-3 py-1 text-xs text-cyan-700">Контекст</span>
|
||||
</div>
|
||||
<p class="mt-2 text-slate-600">После каждого ответа бот выдаёт примеры и пояснения, чтобы закрепить материал.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-surface fade-up" style="animation-delay: 0.12s">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="flex h-12 w-12 items-center justify-center rounded-full bg-blue-50 text-blue-700">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12h6m-3-3v6m8-3a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm text-slate-500">Адаптация под уровень</p>
|
||||
<h3 class="font-heading text-xl">Сложность растёт вместе с тобой</h3>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-3 text-sm text-slate-600">Бот повышает сложность, когда ответы стабильны, и снижает, если нужна поддержка.</p>
|
||||
<div class="mt-4 space-y-2 text-xs text-slate-700">
|
||||
<div class="flex items-center justify-between rounded-lg bg-slate-100 px-3 py-2">
|
||||
<span>CEFR A1–C2</span>
|
||||
<span class="rounded-full bg-blue-50 px-2 py-1 text-blue-700">EN</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between rounded-lg bg-slate-100 px-3 py-2">
|
||||
<span>JLPT N5–N1</span>
|
||||
<span class="rounded-full bg-indigo-50 px-2 py-1 text-indigo-700">JP</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
9
app/layouts/default.vue
Normal file
9
app/layouts/default.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<div class="relative min-h-screen bg-slate-50 text-slate-900">
|
||||
<div class="pointer-events-none absolute inset-0 gradient-ring"></div>
|
||||
<div class="absolute inset-x-0 top-0 h-56 bg-gradient-to-br from-blue-100 via-indigo-50 to-transparent blur-3xl opacity-80"></div>
|
||||
<main class="relative z-10">
|
||||
<slot />
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
13
app/pages/index.vue
Normal file
13
app/pages/index.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div class="relative">
|
||||
<Hero />
|
||||
<Features />
|
||||
<Languages />
|
||||
<SmartDictionary />
|
||||
<Tasks />
|
||||
<Dialogs />
|
||||
<Progress />
|
||||
<CTA />
|
||||
<Footer />
|
||||
</div>
|
||||
</template>
|
||||
70
assets/css/tailwind.css
Normal file
70
assets/css/tailwind.css
Normal file
@@ -0,0 +1,70 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--font-heading: 'Space Grotesk', 'Manrope', system-ui, -apple-system, sans-serif;
|
||||
--font-body: 'Manrope', system-ui, -apple-system, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-slate-50 text-slate-900 font-body antialiased;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
.font-heading {
|
||||
font-family: var(--font-heading);
|
||||
}
|
||||
.font-body {
|
||||
font-family: var(--font-body);
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.shadow-card {
|
||||
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.12);
|
||||
}
|
||||
.shadow-floating {
|
||||
box-shadow: 0 14px 42px rgba(59, 130, 246, 0.18);
|
||||
}
|
||||
}
|
||||
|
||||
.gradient-ring {
|
||||
background: radial-gradient(circle at 20% 20%, rgba(59, 130, 246, 0.12), transparent 35%),
|
||||
radial-gradient(circle at 80% 10%, rgba(14, 165, 233, 0.12), transparent 32%),
|
||||
radial-gradient(circle at 50% 80%, rgba(99, 102, 241, 0.1), transparent 30%);
|
||||
}
|
||||
|
||||
.section-shell {
|
||||
@apply relative overflow-hidden rounded-3xl border border-slate-200 bg-white/95 backdrop-blur shadow-card;
|
||||
}
|
||||
|
||||
.card-surface {
|
||||
@apply rounded-2xl border border-slate-200 bg-white p-6 shadow-card transition duration-300;
|
||||
}
|
||||
|
||||
.card-surface:hover {
|
||||
transform: translateY(-0.25rem);
|
||||
box-shadow: 0 12px 34px rgba(59, 130, 246, 0.16);
|
||||
}
|
||||
|
||||
.badge {
|
||||
@apply inline-flex items-center gap-2 rounded-full bg-blue-50 px-3 py-1 text-xs font-semibold uppercase tracking-wide text-blue-700;
|
||||
}
|
||||
|
||||
.fade-up {
|
||||
opacity: 0;
|
||||
animation: fade-up 0.9s ease forwards;
|
||||
}
|
||||
|
||||
@keyframes fade-up {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
66
nuxt.config.ts
Normal file
66
nuxt.config.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { defineNuxtConfig } from 'nuxt/config'
|
||||
|
||||
export default defineNuxtConfig({
|
||||
compatibilityDate: '2025-07-15',
|
||||
|
||||
modules: [
|
||||
'@nuxt/image-edge',
|
||||
'@nuxt/fonts',
|
||||
'@nuxtjs/tailwindcss',
|
||||
'@nuxtjs/seo'
|
||||
],
|
||||
|
||||
app: {
|
||||
head: {
|
||||
title: 'AI Telegram Bot — изучение английского и японского',
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content:
|
||||
'Умный Telegram-бот для изучения английского (A1–C2) и японского (N5–N1). Словарь, задания, диалоги, прогресс — всё в одном месте.'
|
||||
},
|
||||
{
|
||||
property: 'og:title',
|
||||
content: 'AI Telegram Bot — изучение английского и японского'
|
||||
},
|
||||
{
|
||||
property: 'og:description',
|
||||
content:
|
||||
'Умный Telegram-бот для изучения английского (A1–C2) и японского (N5–N1). Словарь, задания, диалоги, прогресс — всё в одном месте.'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
css: ['~/assets/css/tailwind.css'],
|
||||
|
||||
postcss: {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
}
|
||||
},
|
||||
|
||||
// ⬇ fonts-блок можно вообще убрать, модуль @nuxt/fonts работает и без конфигурации
|
||||
// если хочешь — потом вернём сюда тонкую настройку
|
||||
// fonts: { ... }
|
||||
|
||||
// Это именно то, что ожидает Nuxt SEO: блок `site` в nuxt.config
|
||||
site: {
|
||||
url: process.env.NUXT_PUBLIC_SITE_URL || 'https://language.animeenigma.ru/',
|
||||
name: 'Anime Enigma Language Bot',
|
||||
description:
|
||||
'Умный Telegram-бот для изучения английского (A1–C2) и японского (N5–N1). Словарь, задания, диалоги, прогресс — всё в одном месте.'
|
||||
},
|
||||
|
||||
runtimeConfig: {
|
||||
public: {
|
||||
siteName: 'Anime Enigma Language Bot',
|
||||
apiBase: process.env.NUXT_PUBLIC_API_BASE || 'http://localhost:8000'
|
||||
}
|
||||
},
|
||||
|
||||
tailwindcss: {
|
||||
viewer: false
|
||||
}
|
||||
})
|
||||
16266
package-lock.json
generated
Normal file
16266
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
package.json
Normal file
26
package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "landing-eng-bot",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "nuxt build",
|
||||
"dev": "nuxt dev",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"postinstall": "nuxt prepare"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxtjs/seo": "^3.2.2",
|
||||
"nuxt": "^4.2.1",
|
||||
"vue": "^3.5.25",
|
||||
"vue-router": "^4.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/fonts": "^0.10.3",
|
||||
"@nuxt/image-edge": "^1.3.0-28493895.369b747",
|
||||
"@nuxtjs/tailwindcss": "^6.12.0",
|
||||
"autoprefixer": "^10.4.22",
|
||||
"postcss": "^8.5.6",
|
||||
"tailwindcss": "^3.4.18"
|
||||
}
|
||||
}
|
||||
4
public/_robots.txt
Normal file
4
public/_robots.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
|
||||
Sitemap: https://language.animeenigma.ru/sitemap.xml
|
||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
43
tailwind.config.ts
Normal file
43
tailwind.config.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { Config } from 'tailwindcss'
|
||||
|
||||
export default {
|
||||
content: [
|
||||
'./components/**/*.{vue,js,ts}',
|
||||
'./layouts/**/*.{vue,js,ts}',
|
||||
'./pages/**/*.{vue,js,ts}',
|
||||
'./app/**/*.{vue,js,ts}',
|
||||
'./nuxt.config.{js,ts}'
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
heading: ['var(--font-heading)', 'Space Grotesk', 'sans-serif'],
|
||||
body: ['var(--font-body)', 'Manrope', 'sans-serif']
|
||||
},
|
||||
colors: {
|
||||
primary: '#7C3AED',
|
||||
secondary: '#2563EB',
|
||||
accent: '#0EA5E9',
|
||||
surface: '#0F172A',
|
||||
card: '#0B1020'
|
||||
},
|
||||
backgroundImage: {
|
||||
'hero-gradient': 'linear-gradient(135deg, #7C3AED 0%, #2563EB 50%, #0EA5E9 100%)',
|
||||
'card-gradient': 'linear-gradient(145deg, rgba(124,58,237,0.12), rgba(37,99,235,0.08))'
|
||||
},
|
||||
boxShadow: {
|
||||
glow: '0 10px 40px rgba(124, 58, 237, 0.35)'
|
||||
},
|
||||
keyframes: {
|
||||
'fade-up': {
|
||||
'0%': { opacity: '0', transform: 'translateY(20px)' },
|
||||
'100%': { opacity: '1', transform: 'translateY(0)' }
|
||||
}
|
||||
},
|
||||
animation: {
|
||||
'fade-up': 'fade-up 0.9s ease forwards'
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: []
|
||||
} satisfies Config
|
||||
16
tsconfig.json
Normal file
16
tsconfig.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./.nuxt/tsconfig.app.json" },
|
||||
{ "path": "./.nuxt/tsconfig.server.json" },
|
||||
{ "path": "./.nuxt/tsconfig.shared.json" },
|
||||
{ "path": "./.nuxt/tsconfig.node.json" }
|
||||
],
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./*"],
|
||||
"~/*": ["./*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user