diff --git a/Dockerfile b/Dockerfile
index f41bd16..b6bd0cb 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -86,7 +86,6 @@ EXPOSE 3002
ENV NODE_ENV=production \
DB_FILE="db/production.sqlite3" \
PORT=3002 \
- TUDUDI_INTERNAL_SSL_ENABLED=false \
TUDUDI_ALLOWED_ORIGINS="http://localhost:8080,http://localhost:3002,http://127.0.0.1:8080,http://127.0.0.1:3002" \
TUDUDI_SESSION_SECRET="" \
TUDUDI_USER_EMAIL="" \
diff --git a/README.md b/README.md
index 5685cf3..14ef48e 100644
--- a/README.md
+++ b/README.md
@@ -94,7 +94,6 @@ The following environment variables are used to configure tududi:
#### Optional Variables:
- `PUID`, `GUID` - Run with specified user and group ID (instead of defaults 1001/1001)
-- `TUDUDI_INTERNAL_SSL_ENABLED` - Set to 'true' if using HTTPS internally (default: false)
- `TUDUDI_ALLOWED_ORIGINS` - Controls CORS access for different deployment scenarios:
- Not set: Only allows localhost origins
- Specific domains: `https://tududi.com,http://localhost:3002`
@@ -107,7 +106,6 @@ The following environment variables are used to configure tududi:
export TUDUDI_USER_EMAIL=dev@local.test
export TUDUDI_USER_PASSWORD=devpassword123
export TUDUDI_SESSION_SECRET=$(openssl rand -hex 64)
-export TUDUDI_INTERNAL_SSL_ENABLED=false
# TUDUDI_ALLOWED_ORIGINS not set - defaults to localhost only
```
@@ -116,7 +114,6 @@ export TUDUDI_INTERNAL_SSL_ENABLED=false
export TUDUDI_USER_EMAIL=admin@yourdomain.com
export TUDUDI_USER_PASSWORD=your-secure-password-here
export TUDUDI_SESSION_SECRET=$(openssl rand -hex 64)
-export TUDUDI_INTERNAL_SSL_ENABLED=true
export TUDUDI_ALLOWED_ORIGINS=https://tududi.yourdomain.com
```
@@ -127,7 +124,6 @@ docker run \
-e TUDUDI_USER_EMAIL=myemail@example.com \
-e TUDUDI_USER_PASSWORD=mysecurepassword \
-e TUDUDI_SESSION_SECRET=$(openssl rand -hex 64) \
- -e TUDUDI_INTERNAL_SSL_ENABLED=false \
-e TUDUDI_ALLOWED_ORIGINS=https://tududi,http://tududi:3002 \
-e PUID=1001 \
-e GUID=1001 \
@@ -254,22 +250,6 @@ To install `tududi`, follow these steps:
npm install
```
-### đ SSL Setup (Optional)
-
-For HTTPS support, create SSL certificates:
-
-1. Create and enter the directory:
- ```bash
- mkdir backend/certs
- cd backend/certs
- ```
-2. Create the key and cert:
- ```bash
- openssl genrsa -out server.key 2048
- openssl req -new -x509 -key server.key -out server.crt -days 365
- cd ../..
- ```
-
### đ Database Setup
The database will be automatically initialized when you start the Express backend. For manual database operations:
diff --git a/backend/app.js b/backend/app.js
index 504527e..3a0cfcf 100644
--- a/backend/app.js
+++ b/backend/app.js
@@ -23,9 +23,9 @@ const sessionStore = new SequelizeStore({
// Middlewares
app.use(
helmet({
- hsts: config.sslEnabled, // Only enable HSTS when SSL is enabled
- forceHTTPS: config.sslEnabled, // Only force HTTPS when SSL is enabled
- contentSecurityPolicy: false, // Disable CSP for now to avoid conflicts
+ hsts: false,
+ forceHTTPS: false,
+ contentSecurityPolicy: false,
})
);
app.use(compression());
@@ -61,9 +61,9 @@ app.use(
saveUninitialized: false,
cookie: {
httpOnly: true,
- secure: config.sslEnabled,
+ secure: false,
maxAge: 2592000000, // 30 days
- sameSite: config.sslEnabled ? 'none' : 'lax',
+ sameSite: 'lax',
},
})
);
diff --git a/backend/cmd/start.sh b/backend/cmd/start.sh
index c9da6b0..2379d85 100755
--- a/backend/cmd/start.sh
+++ b/backend/cmd/start.sh
@@ -47,6 +47,4 @@ if [ -n "${TUDUDI_USER_EMAIL:-}" ] && [ -n "${TUDUDI_USER_PASSWORD:-}" ]; then
node -e "const{User}=require(\"./models\");const bcrypt=require(\"bcrypt\");(async()=>{try{const[u,c]=await User.findOrCreate({where:{email:process.env.TUDUDI_USER_EMAIL},defaults:{email:process.env.TUDUDI_USER_EMAIL,password_digest:await bcrypt.hash(process.env.TUDUDI_USER_PASSWORD,10)}});console.log(c?\"â
User created\":\"âšī¸ User exists\");process.exit(0)}catch(e){console.error(\"â\",e.message);process.exit(1)}})();" || exit 1
fi
-[ "${TUDUDI_INTERNAL_SSL_ENABLED:-}" = "true" ] && [ ! -f "certs/server.crt" ] && openssl req -x509 -newkey rsa:2048 -keyout certs/server.key -out certs/server.crt -days 365 -nodes -subj "/CN=localhost" 2>/dev/null || true
-
exec node app.js
diff --git a/backend/config/config.js b/backend/config/config.js
index 86af874..038b2ef 100644
--- a/backend/config/config.js
+++ b/backend/config/config.js
@@ -65,9 +65,6 @@ const config = {
credentials,
- sslEnabled:
- production && process.env.TUDUDI_INTERNAL_SSL_ENABLED === 'true',
-
uploadPath:
process.env.TUDUDI_UPLOAD_PATH || path.join(projectRootPath, 'uploads'),
};
diff --git a/docker-compose.yml b/docker-compose.yml
index edc0e4b..2d01a3a 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -6,7 +6,6 @@ services:
- TUDUDI_USER_EMAIL=admin@example.com
- TUDUDI_USER_PASSWORD=your-secure-password
- TUDUDI_SESSION_SECRET=changeme-please-use-openssl
- - TUDUDI_INTERNAL_SSL_ENABLED=false
- TUDUDI_ALLOWED_ORIGINS=http://localhost:3002
- TUDUDI_UPLOAD_PATH="/app/backend/uploads"
# Runtime UID/GID configuration - set these to match your host user/group
diff --git a/index.html b/index.html
index 468605d..2671945 100644
--- a/index.html
+++ b/index.html
@@ -10,7 +10,7 @@
gtag('config', 'G-VC2N7ZBPEE');
-
+
tududi - Self-Hosted Task & Project Management
@@ -27,7 +27,7 @@
--light-color: #f8fafc;
--dark-color: #0f172a;
--success-color: #059669;
-
+
--bg-color: #ffffff;
--text-color: #1e293b;
--text-muted: #64748b;
@@ -40,7 +40,7 @@
--gradient-elegant: linear-gradient(135deg, #f0b575 0%, #e0a465 100%);
--gradient-surface: linear-gradient(145deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%);
}
-
+
[data-theme="dark"] {
--primary-color: #3b82f6;
--primary-hover: #2563eb;
@@ -49,7 +49,7 @@
--light-color: #1e293b;
--dark-color: #f1f5f9;
--success-color: #10b981;
-
+
--bg-color: #0f172a;
--text-color: #f1f5f9;
--text-muted: #94a3b8;
@@ -62,17 +62,17 @@
--gradient-elegant: linear-gradient(135deg, #f0b575 0%, #e0a465 100%);
--gradient-surface: linear-gradient(145deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.02) 100%);
}
-
+
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
-
+
html {
scroll-behavior: smooth;
}
-
+
@keyframes fadeInUp {
from {
opacity: 0;
@@ -83,7 +83,7 @@
transform: translateY(0);
}
}
-
+
@keyframes float {
0%, 100% {
transform: translateY(0);
@@ -92,7 +92,7 @@
transform: translateY(-10px);
}
}
-
+
body {
line-height: 1.7;
color: var(--text-color);
@@ -103,14 +103,14 @@
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
-
+
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 15px;
}
-
+
/* Header */
header {
background: rgba(255, 255, 255, 0.95);
@@ -123,12 +123,12 @@
z-index: 1000;
transition: all 0.3s ease;
}
-
+
[data-theme="dark"] header {
background: rgba(15, 23, 42, 0.95);
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
-
+
header::before {
content: '';
position: absolute;
@@ -139,14 +139,14 @@
background: var(--gradient-primary);
opacity: 0.3;
}
-
+
nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 0;
}
-
+
.logo {
display: flex;
align-items: center;
@@ -156,40 +156,40 @@
text-decoration: none;
transition: all 0.3s ease;
}
-
+
[data-theme="dark"] .logo {
color: white;
}
-
+
.logo:hover {
transform: translateY(-1px);
}
-
+
.logo-icon {
margin-right: 8px;
display: flex;
align-items: center;
justify-content: center;
}
-
+
.logo-icon svg {
color: #1e293b;
}
-
+
[data-theme="dark"] .logo-icon svg {
color: white;
}
-
+
.nav-links {
display: flex;
list-style: none;
align-items: center;
}
-
+
.nav-links li {
margin-left: 8px;
}
-
+
.nav-links a {
text-decoration: none;
color: var(--text-color);
@@ -199,7 +199,7 @@
padding: 8px 16px;
border-radius: 8px;
}
-
+
.nav-links a::before {
content: '';
position: absolute;
@@ -211,41 +211,41 @@
transition: all 0.3s ease;
transform: translateX(-50%);
}
-
+
.nav-links a:hover {
color: var(--primary-color);
background: rgba(37, 99, 235, 0.05);
}
-
+
.nav-links a:hover::before {
width: 100%;
}
-
+
.theme-switch {
margin-left: 8px;
display: flex;
align-items: center;
}
-
+
.theme-switch-label {
margin-right: 10px;
font-size: 0.9rem;
color: var(--text-color);
}
-
+
.switch {
position: relative;
display: inline-block;
width: 50px;
height: 24px;
}
-
+
.switch input {
opacity: 0;
width: 0;
height: 0;
}
-
+
.slider {
position: absolute;
cursor: pointer;
@@ -257,7 +257,7 @@
transition: .4s;
border-radius: 24px;
}
-
+
.slider:before {
position: absolute;
content: "";
@@ -269,15 +269,15 @@
transition: .4s;
border-radius: 50%;
}
-
+
input:checked + .slider {
background-color: var(--primary-color);
}
-
+
input:checked + .slider:before {
transform: translateX(26px);
}
-
+
.cta-button {
background: var(--gradient-primary);
color: white;
@@ -288,13 +288,13 @@
transition: all 0.3s ease;
box-shadow: var(--shadow-sm);
}
-
+
.cta-button:hover {
transform: translateY(-1px);
box-shadow: var(--shadow-md);
color: white;
}
-
+
/* Hero Section */
.hero {
padding: 220px 0 120px;
@@ -303,7 +303,7 @@
position: relative;
overflow: hidden;
}
-
+
.hero::before {
content: '';
position: absolute;
@@ -314,7 +314,7 @@
background: url('data:image/svg+xml,') repeat;
opacity: 0.6;
}
-
+
.hero::after {
content: '';
position: absolute;
@@ -324,14 +324,14 @@
bottom: 0;
background: radial-gradient(circle at 50% 50%, rgba(255,255,255,0.1) 0%, transparent 70%);
}
-
+
.hero-content {
max-width: 900px;
margin: 0 auto;
position: relative;
z-index: 1;
}
-
+
.hero h1 {
font-size: 3.5rem;
font-weight: 800;
@@ -344,56 +344,56 @@
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
animation: fadeInUp 0.8s ease-out;
}
-
+
[data-theme="dark"] .hero h1 {
color: white;
}
-
+
[data-theme="dark"] .hero p {
color: rgba(255, 255, 255, 0.9);
}
-
+
[data-theme="dark"] .github-stars-display {
color: rgba(255, 255, 255, 0.8) !important;
}
-
+
[data-theme="dark"] .testimonials .section-header h2 {
color: white !important;
}
-
+
[data-theme="dark"] .testimonials .section-header p {
color: rgba(255, 255, 255, 0.9) !important;
}
-
+
.testimonial-quote {
color: #2d3748;
}
-
+
.testimonial-source {
color: #4a5568;
}
-
+
[data-theme="dark"] .testimonial-quote {
color: white !important;
}
-
+
[data-theme="dark"] .testimonial-source {
color: rgba(255, 255, 255, 0.8) !important;
}
-
+
.testimonial-card {
background: white;
border: 1px solid rgba(0, 0, 0, 0.1);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
-
+
[data-theme="dark"] .testimonial-card {
background: rgba(255, 255, 255, 0.15) !important;
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.2) !important;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3) !important;
}
-
+
.hero-subtitle {
font-size: 1.5rem;
font-weight: 400;
@@ -403,11 +403,11 @@
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
animation: fadeInUp 0.8s ease-out 0.1s both;
}
-
+
.hero-spacer {
height: 40px;
}
-
+
.hero p {
font-size: 1.3rem;
color: #4a5568;
@@ -420,7 +420,7 @@
z-index: 1;
animation: fadeInUp 0.8s ease-out 0.2s both;
}
-
+
.hero-buttons {
display: flex;
justify-content: center;
@@ -432,7 +432,7 @@
z-index: 1;
animation: fadeInUp 0.8s ease-out 0.4s both;
}
-
+
.hero-buttons a {
text-decoration: none;
padding: 16px 32px;
@@ -444,33 +444,33 @@
align-items: center;
gap: 8px;
}
-
+
.primary-button {
background-color: white;
color: var(--primary-color);
box-shadow: var(--shadow-lg);
}
-
+
.primary-button:hover {
transform: translateY(-2px);
box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
}
-
+
.secondary-button {
border: 2px solid var(--primary-color);
color: var(--primary-color);
}
-
+
.secondary-button:hover {
background-color: var(--primary-color);
color: white;
}
-
+
[data-theme="dark"] .secondary-button {
border: 2px solid white;
color: white;
}
-
+
[data-theme="dark"] .secondary-button:hover {
background-color: white;
color: var(--primary-color);
@@ -496,13 +496,13 @@
height: 100%;
border-radius: 5px;
}
-
+
.hero-image-container {
margin-bottom: 40px;
position: relative;
z-index: 1;
}
-
+
.mobile-overlay {
position: absolute;
bottom: -20px;
@@ -516,23 +516,23 @@
pointer-events: none;
animation: fadeInUp 0.8s ease-out 0.8s both;
}
-
+
.mobile-overlay-light {
display: block;
}
-
+
.mobile-overlay-dark {
display: none;
}
-
+
[data-theme="dark"] .mobile-overlay-light {
display: none;
}
-
+
[data-theme="dark"] .mobile-overlay-dark {
display: block;
}
-
+
@media (max-width: 768px) {
.mobile-overlay {
width: 120px;
@@ -540,7 +540,7 @@
right: -10px;
}
}
-
+
.hero-image {
max-width: 100%;
width: 100%;
@@ -550,33 +550,33 @@
transition: all 0.3s ease;
animation: fadeInUp 0.8s ease-out 0.6s both;
}
-
+
.hero-image-light {
display: block;
}
-
+
.hero-image-dark {
display: none;
}
-
+
[data-theme="dark"] .hero-image-light {
display: none;
}
-
+
[data-theme="dark"] .hero-image-dark {
display: block;
}
-
+
/* Features */
.features {
padding: 120px 0;
background-color: var(--light-color);
}
-
+
[data-theme="dark"] .features {
background-color: var(--bg-color);
}
-
+
.section-header {
text-align: center;
margin-bottom: 80px;
@@ -584,7 +584,7 @@
margin-left: auto;
margin-right: auto;
}
-
+
.section-header h2 {
font-size: 2.4rem;
font-weight: 800;
@@ -593,7 +593,7 @@
line-height: 1.2;
letter-spacing: -0.02em;
}
-
+
.section-header p {
font-size: 1.25rem;
color: var(--text-muted);
@@ -601,13 +601,13 @@
max-width: 700px;
margin: 0 auto;
}
-
+
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
}
-
+
.feature-card {
background-color: var(--card-bg);
padding: 24px 20px;
@@ -619,7 +619,7 @@
position: relative;
overflow: hidden;
}
-
+
.feature-card::before {
content: '';
position: absolute;
@@ -630,7 +630,7 @@
background: var(--gradient-primary);
transition: all 0.3s ease;
}
-
+
.feature-card::after {
content: '';
position: absolute;
@@ -641,20 +641,20 @@
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.1), transparent);
transition: left 0.5s ease;
}
-
+
.feature-card:hover {
transform: translateY(-8px) scale(1.02);
box-shadow: var(--shadow-lg);
}
-
+
.feature-card:hover::after {
left: 100%;
}
-
+
.feature-card:hover::before {
height: 6px;
}
-
+
.feature-icon {
background: var(--gradient-primary);
color: white;
@@ -668,7 +668,7 @@
font-size: 1.2rem;
box-shadow: var(--shadow-md);
}
-
+
.feature-card h3 {
font-size: 1.2rem;
font-weight: 700;
@@ -676,13 +676,13 @@
color: var(--text-color);
line-height: 1.3;
}
-
+
.feature-card p {
color: var(--text-muted);
line-height: 1.6;
font-size: 0.9rem;
}
-
+
/* Languages Section */
.languages {
padding: 100px 0;
@@ -691,7 +691,7 @@
position: relative;
overflow: hidden;
}
-
+
.languages::before {
content: '';
position: absolute;
@@ -702,27 +702,27 @@
background: url('data:image/svg+xml,');
opacity: 0.3;
}
-
+
.languages .container {
position: relative;
z-index: 1;
}
-
+
.languages .section-header {
margin-bottom: 60px;
}
-
+
.languages .section-header h2 {
color: white;
font-size: 2.8rem;
margin-bottom: 20px;
}
-
+
.languages .section-header p {
color: rgba(255, 255, 255, 0.9);
font-size: 1.2rem;
}
-
+
.languages-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
@@ -730,7 +730,7 @@
max-width: 1000px;
margin: 0 auto;
}
-
+
.language-item {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
@@ -741,21 +741,21 @@
transition: all 0.3s ease;
cursor: pointer;
}
-
+
.language-item:hover {
transform: translateY(-5px) scale(1.02);
background: rgba(255, 255, 255, 0.15);
border-color: rgba(255, 255, 255, 0.4);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}
-
+
.language-flag {
font-size: 2.5rem;
margin-bottom: 10px;
display: block;
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
}
-
+
.language-name {
font-weight: 600;
font-size: 0.9rem;
@@ -763,44 +763,44 @@
margin: 0;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
-
-
+
+
/* Screenshots */
.screenshots {
padding: 100px 0;
background-color: var(--card-bg);
}
-
+
.screenshots-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 30px;
margin-top: 50px;
}
-
+
.screenshot {
border-radius: 6px;
overflow: hidden;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
-
+
.screenshot img {
width: 100%;
height: auto;
display: block;
transition: transform 0.3s;
}
-
+
.screenshot:hover img {
transform: scale(1.03);
}
-
+
/* Installation */
.installation {
padding: 100px 0;
background-color: var(--bg-color);
}
-
+
.installation-steps {
max-width: 800px;
margin: 0 auto;
@@ -809,17 +809,17 @@
padding: 40px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
}
-
+
.step {
margin-bottom: 30px;
display: flex;
align-items: flex-start;
}
-
+
.step:last-child {
margin-bottom: 0;
}
-
+
.step-number {
background-color: var(--primary-color);
color: white;
@@ -833,18 +833,18 @@
margin-right: 15px;
flex-shrink: 0;
}
-
+
.step-content h3 {
font-size: 1.3rem;
margin-bottom: 10px;
color: var(--text-color);
}
-
+
.step-content p {
color: var(--secondary-color);
margin-bottom: 15px;
}
-
+
code {
background-color: #f0f0f0;
padding: 10px 15px;
@@ -855,12 +855,12 @@
white-space: pre-wrap;
color: #333;
}
-
+
[data-theme="dark"] code {
background-color: #2a2a2a;
color: #f0f0f0;
}
-
+
/* CTA */
.cta {
padding: 100px 0;
@@ -868,24 +868,24 @@
color: white;
text-align: center;
}
-
+
.cta h2 {
font-size: 2.5rem;
margin-bottom: 20px;
}
-
+
.cta p {
font-size: 1.2rem;
max-width: 700px;
margin: 0 auto 30px;
}
-
+
.cta-buttons {
display: flex;
justify-content: center;
gap: 20px;
}
-
+
.cta-white {
background-color: white;
color: var(--primary-color);
@@ -895,11 +895,11 @@
font-weight: 600;
transition: background-color 0.3s;
}
-
+
.cta-white:hover {
background-color: #f0f0f0;
}
-
+
.cta-outline {
border: 2px solid white;
color: white;
@@ -909,32 +909,32 @@
font-weight: 600;
transition: background-color 0.3s;
}
-
+
.cta-outline:hover {
background-color: rgba(255, 255, 255, 0.1);
}
-
+
/* Footer */
footer {
background-color: #212121;
color: white;
padding: 60px 0 30px;
}
-
+
.footer-content {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 40px;
margin-bottom: 40px;
}
-
+
.footer-column h3 {
font-size: 1.3rem;
margin-bottom: 20px;
position: relative;
padding-bottom: 10px;
}
-
+
.footer-column h3::after {
content: '';
position: absolute;
@@ -944,25 +944,25 @@
height: 2px;
background-color: var(--primary-color);
}
-
+
.footer-links {
list-style: none;
}
-
+
.footer-links li {
margin-bottom: 10px;
}
-
+
.footer-links a {
color: #b0b0b0;
text-decoration: none;
transition: color 0.3s;
}
-
+
.footer-links a:hover {
color: white;
}
-
+
.footer-bottom {
text-align: center;
padding-top: 30px;
@@ -970,47 +970,47 @@
color: #b0b0b0;
font-size: 0.9rem;
}
-
+
.social-icons {
display: flex;
gap: 15px;
margin-top: 20px;
}
-
+
.social-icons a {
color: white;
font-size: 1.2rem;
transition: color 0.3s;
}
-
+
.social-icons a:hover {
color: var(--primary-color);
}
-
+
.mobile-menu-toggle {
display: none;
}
-
+
/* Responsive */
@media (max-width: 768px) {
.container {
padding: 0 20px;
}
-
+
/* Header */
nav {
padding: 15px 0;
}
-
+
.logo {
font-size: 1.5rem;
}
-
+
.logo-icon svg {
width: 24px;
height: 24px;
}
-
+
.nav-links {
display: none;
position: fixed;
@@ -1025,11 +1025,11 @@
box-shadow: var(--shadow-lg);
z-index: 1000;
}
-
+
.nav-links.active {
display: flex;
}
-
+
.mobile-menu-toggle {
display: block;
background: none;
@@ -1039,49 +1039,49 @@
cursor: pointer;
padding: 5px;
}
-
+
.nav-links a {
padding: 10px 15px;
border-radius: 8px;
text-align: center;
}
-
+
.theme-switch {
justify-content: center;
margin: 10px 0;
}
-
+
/* Hero */
.hero {
padding: 150px 0 60px;
text-align: center;
}
-
+
.hero h1 {
font-size: 2.2rem;
margin-bottom: 12px;
}
-
+
.hero-subtitle {
font-size: 1.1rem;
margin-bottom: 20px;
}
-
+
.hero-spacer {
height: 25px;
}
-
+
.hero p {
font-size: 1rem;
margin-bottom: 30px;
}
-
+
.hero-buttons {
flex-direction: column;
gap: 12px;
align-items: center;
}
-
+
.hero-buttons a {
width: 100%;
max-width: 280px;
@@ -1089,28 +1089,28 @@
padding: 12px 20px;
font-size: 0.95rem;
}
-
+
.hero-image {
max-width: 100%;
margin-bottom: 30px;
}
-
+
/* Sections */
.section-header h2 {
font-size: 2rem;
margin-bottom: 12px;
}
-
+
.section-header p {
font-size: 0.95rem;
}
-
+
/* Features */
.features-grid {
grid-template-columns: 1fr;
gap: 20px;
}
-
+
.feature-card {
padding: 20px;
text-align: left;
@@ -1120,7 +1120,7 @@
gap: 15px 15px;
align-items: start;
}
-
+
.feature-icon {
grid-row: 1 / 3;
grid-column: 1;
@@ -1128,7 +1128,7 @@
align-self: start;
margin-top: 3px;
}
-
+
.feature-card h3 {
grid-row: 1;
grid-column: 2;
@@ -1136,7 +1136,7 @@
margin: 0;
align-self: start;
}
-
+
.feature-card p {
grid-row: 2;
grid-column: 2;
@@ -1145,12 +1145,12 @@
line-height: 1.4;
align-self: start;
}
-
+
/* Testimonials */
.testimonials {
padding: 50px 0;
}
-
+
.testimonial-card {
padding: 25px 20px !important;
flex-direction: column;
@@ -1160,7 +1160,7 @@
background: rgba(255, 255, 255, 0.95) !important;
backdrop-filter: blur(10px) !important;
}
-
+
.testimonial-card blockquote {
font-size: 1.1rem !important;
order: 2;
@@ -1169,116 +1169,116 @@
line-height: 1.5;
margin: 0 !important;
}
-
+
.testimonial-card > div:first-child {
font-size: 2.5rem !important;
order: 1;
}
-
+
.testimonial-card > div:last-child {
order: 3;
justify-content: center;
color: #4a5568 !important;
font-weight: 600;
}
-
+
/* Languages */
.languages-grid {
grid-template-columns: repeat(3, 1fr);
gap: 15px;
}
-
+
.language-item {
padding: 10px;
}
-
+
.language-flag {
font-size: 1.5rem;
}
-
+
.language-name {
font-size: 0.8rem;
}
-
+
/* Screenshots */
.screenshots-grid {
grid-template-columns: 1fr;
gap: 20px;
}
-
+
/* Installation */
.installation-steps {
gap: 30px;
}
-
+
.step {
flex-direction: column;
text-align: center;
gap: 15px;
}
-
+
.step-number {
margin: 0 auto 15px;
}
-
+
.step-content h3 {
font-size: 1.1rem;
word-wrap: break-word;
}
-
+
.step-content p {
font-size: 0.9rem;
}
-
+
.step-content code {
font-size: 0.8rem;
word-break: break-all;
white-space: pre-wrap;
overflow-wrap: break-word;
}
-
+
.step-content div {
margin: 10px 0;
overflow: hidden;
}
-
+
.step-content h4 {
font-size: 1rem !important;
word-wrap: break-word;
}
-
+
.step-content ul {
text-align: left;
padding-left: 15px !important;
}
-
+
.step-content li {
font-size: 0.85rem;
margin-bottom: 8px;
word-wrap: break-word;
}
-
+
.step-content strong {
word-wrap: break-word;
display: inline-block;
max-width: 100%;
}
-
+
/* CTA */
.cta h2 {
font-size: 2rem;
}
-
+
.cta p {
font-size: 0.95rem;
}
-
+
.cta-buttons {
flex-direction: column;
gap: 12px;
align-items: center;
}
-
+
.cta-buttons a {
width: 100%;
max-width: 280px;
@@ -1357,14 +1357,14 @@
20% { opacity: 0; transform: translateY(-20px); }
100% { opacity: 0; transform: translateY(-20px); }
}
-
+
.testimonial-card {
animation: testimonialFade 20s infinite;
position: absolute;
width: 100%;
opacity: 0;
}
-
+
.testimonial-card:nth-child(1) { animation-delay: 0s; }
.testimonial-card:nth-child(2) { animation-delay: 4s; }
.testimonial-card:nth-child(3) { animation-delay: 8s; }
@@ -1697,7 +1697,6 @@
Optional Variables:
- - TUDUDI_INTERNAL_SSL_ENABLED - Set to 'true' for HTTPS
- TUDUDI_ALLOWED_ORIGINS - Controls CORS access
@@ -1713,7 +1712,6 @@
-e TUDUDI_USER_EMAIL=myemail@example.com \
-e TUDUDI_USER_PASSWORD=mysecurepassword \
-e TUDUDI_SESSION_SECRET=$(openssl rand -hex 64) \
- -e TUDUDI_INTERNAL_SSL_ENABLED=false \
-e TUDUDI_ALLOWED_ORIGINS=https://tududi,http://tududi:3002 \
-v ~/tududi_db:/app/backend/db \
-v ~/tududi_uploads:/app/backend/uploads \
@@ -1845,15 +1843,15 @@