Initial commit: Deklinationstrainer German declension trainer
Vite + React app for daily German declension practice with localStorage-backed progress. Includes Coolify deploy instructions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
.DS_Store
|
||||||
|
*.log
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Deklinationstrainer
|
||||||
|
|
||||||
|
A daily-practice German declension trainer. Self-hosted so your progress actually saves.
|
||||||
|
|
||||||
|
## Deploy to Coolify
|
||||||
|
|
||||||
|
### One-time setup
|
||||||
|
|
||||||
|
1. Push these files to a git repo (GitHub / Gitea / whatever Coolify is connected to).
|
||||||
|
|
||||||
|
2. In Coolify, create a new **Application**:
|
||||||
|
- Source: your git repo
|
||||||
|
- Build pack: **Nixpacks** (auto-detects Vite) or **Static**
|
||||||
|
- Build command: `npm run build`
|
||||||
|
- Publish directory: `dist`
|
||||||
|
- Port: not needed for static output (Coolify serves it directly)
|
||||||
|
|
||||||
|
3. Add a domain (e.g. `deklination.yourdomain.com`). Coolify provisions HTTPS via Caddy/Traefik automatically.
|
||||||
|
|
||||||
|
4. Deploy. Visit the URL on any device.
|
||||||
|
|
||||||
|
### Local dev
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run dev # http://localhost:5173
|
||||||
|
npm run build # outputs to ./dist
|
||||||
|
```
|
||||||
|
|
||||||
|
## On iPhone
|
||||||
|
|
||||||
|
Open the URL in Safari, tap Share → **Add to Home Screen**. It opens fullscreen like a native app, and progress saves in localStorage across reboots, sessions, and app closes.
|
||||||
|
|
||||||
|
## Storage
|
||||||
|
|
||||||
|
The app tries `window.storage` first (Claude artifact environment), then falls back to `localStorage`. When self-hosted, only localStorage runs, which iOS Safari persists reliably.
|
||||||
|
|
||||||
|
To wipe progress: open browser devtools → Application → Local Storage → delete the `gd-v10` key. Or on iPhone: Settings → Safari → Advanced → Website Data → search your domain → delete.
|
||||||
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
+16
@@ -0,0 +1,16 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover" />
|
||||||
|
<meta name="theme-color" content="#f7f7f7" />
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||||||
|
<meta name="apple-mobile-web-app-title" content="Beug" />
|
||||||
|
<title>Beug</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.jsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Generated
+1680
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "deklinationstrainer",
|
||||||
|
"private": true,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview --host"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^18.3.1",
|
||||||
|
"react-dom": "^18.3.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
|
"vite": "^5.4.11"
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1475
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
|||||||
|
import { StrictMode } from 'react'
|
||||||
|
import { createRoot } from 'react-dom/client'
|
||||||
|
import App from './App.jsx'
|
||||||
|
|
||||||
|
createRoot(document.getElementById('root')).render(
|
||||||
|
<StrictMode>
|
||||||
|
<App />
|
||||||
|
</StrictMode>,
|
||||||
|
)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user