mirror of
https://github.com/IT4Change/IT4C.dev.git
synced 2025-12-13 09:25:49 +00:00
refactor(other): new website structure (#227)
* - added new site /new/README.md - added new components - added component registration "client.js" - added approach for tailwind integration (does not work yet) * Use TypeScript and script setup * No ts for .textlintrc * Make Tailwind work * include heropage contents partially fixes https://github.com/IT4Change/IT4C.dev/issues/221 * adjust contents of Services Adjust contents according to https://github.com/IT4Change/IT4C.dev/issues/222 * added Team & Values texts According to https://github.com/IT4Change/IT4C.dev/issues/223 * fixed type * fixed unreferenced styles/main.css * sample from theme-hope-docu From https://theme-hope.vuejs.press/guide/layout/home.html#project-highlights-and-features * - adapted Hope hero section - removed remaining Hero Widgets - added ContentSection - optimized layout of team section * - optimized layout/style of ContactForm * - made TeamMember functional and added some transitions - added new members as placeholder * Hero at 100vh; transparent navbar on home page * Add text and image for Max * Keep logo text in same row as logo * - added REST request to mail backend - added limitations to contact fields * - added photo and phone number to contact form * - changed contact person and phone number * - replaced hero section - replaced default layout - replaced footer * clean up * - optimized colors * - clean up AI comments * move new page from /new to / * fixed errors with contactForm * fix projects * fix merge error * corrected image for Sebastian * - improved layout * - fixed tag colors - fixed phone number color and hover --------- Co-authored-by: Sebastian Stein <git@codepassion.de> Co-authored-by: Maximilian Harz <maxharz@gmail.com> Co-authored-by: Ulf Gebhardt <ulf.gebhardt@webcraft-media.de> Co-authored-by: Sebastian Stein <sebastian@codepassion.de>
This commit is contained in:
parent
79f679ef4f
commit
3d5d2fff0a
31
docs/.vuepress/client.ts
Normal file
31
docs/.vuepress/client.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { defineClientConfig } from 'vuepress/client'
|
||||
import { setupTransparentNavbar } from "vuepress-theme-hope/presets/transparentNavbar.js";
|
||||
import BlankLayout from './layouts/BlankLayout.vue'
|
||||
import ContactForm from './components/ContactForm.vue'
|
||||
import ContentSection from './components/ContentSection.vue'
|
||||
import Footer from './components/Footer.vue'
|
||||
import ProcessStep from './components/ProcessStep.vue'
|
||||
import ProjectCard from './components/ProjectCard.vue'
|
||||
import ServiceCard from './components/ServiceCard.vue'
|
||||
import TeamMember from './components/TeamMember.vue'
|
||||
|
||||
export default defineClientConfig({
|
||||
enhance({ app }) {
|
||||
app.component('ContactForm', ContactForm)
|
||||
app.component('ContentSection', ContentSection)
|
||||
app.component('Footer', Footer)
|
||||
app.component('ProcessStep', ProcessStep)
|
||||
app.component('ProjectCard', ProjectCard)
|
||||
app.component('TeamMember', TeamMember)
|
||||
app.component('ServiceCard', ServiceCard)
|
||||
|
||||
},
|
||||
setup() {
|
||||
setupTransparentNavbar({ type: "homepage" });
|
||||
},
|
||||
// You can override or add layouts here
|
||||
layouts: {
|
||||
// For example, here we change the default layout of vuepress-theme-hope to layouts/Layout.vue
|
||||
BlankLayout,
|
||||
}
|
||||
})
|
||||
158
docs/.vuepress/components/ContactForm.vue
Normal file
158
docs/.vuepress/components/ContactForm.vue
Normal file
@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<p class="text-gray-600 mb-8">Wir freuen uns auf Ihre Nachricht. Als Ansprechpartner steht Ihnen <strong>Ulf Gebhardt</strong> für Ihre Fragen gerne zur Verfügung.</p>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-5 gap-8">
|
||||
<!-- Left side: Portrait - takes 2/5 of space -->
|
||||
<div class="flex flex-col items-center md:items-start md:self-start md:col-span-2">
|
||||
<img
|
||||
src="/images/portrait/ulf-gebhardt.jpg"
|
||||
alt="Ulf Gebhardt"
|
||||
class="rounded-lg shadow-md w-97 h-auto mb-6"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Right side: Contact form - takes 3/5 of space -->
|
||||
<div class="md:col-span-3">
|
||||
<h3 class="mb-4">Telefon</h3>
|
||||
<div class="flex-col gap-2 mb-8">
|
||||
<p class="flex items-center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="phone-number h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
<a href="tel:+4915784841600" class="phone-number hover:!underline">+49 15784841600</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h3 class="mb-4">Nachricht</h3>
|
||||
<form class="space-y-4" @submit.prevent="handleSubmit">
|
||||
<div v-if="submitSuccess" class="p-3 bg-green-100 text-green-700 rounded-md mb-4">
|
||||
Deine Nachricht wurde erfolgreich gesendet. Vielen Dank!
|
||||
</div>
|
||||
|
||||
<div v-if="submitError" class="p-3 bg-red-100 text-red-700 rounded-md mb-4">
|
||||
{{ submitError }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
v-model="form.name"
|
||||
placeholder="Name"
|
||||
required
|
||||
minlength="2"
|
||||
maxlength="35"
|
||||
class="w-full p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent"
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
v-model="form.email"
|
||||
placeholder="E-Mail"
|
||||
required
|
||||
class="w-full p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent"
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="tel"
|
||||
id="phone"
|
||||
v-model="form.phone"
|
||||
placeholder="Telefon"
|
||||
minlength="8"
|
||||
class="w-full p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent"
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<textarea
|
||||
id="message"
|
||||
v-model="form.message"
|
||||
rows="4"
|
||||
placeholder="Ihre Nachricht"
|
||||
required
|
||||
minlength="5"
|
||||
class="w-full p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent"
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="flex justify-end">
|
||||
<button
|
||||
type="submit"
|
||||
:disabled="isSubmitting"
|
||||
class="bg-green-700 text-white py-2 px-6 rounded-md hover:bg-green-600 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 disabled:bg-green-300 disabled:cursor-not-allowed"
|
||||
>
|
||||
<span v-if="isSubmitting">Wird gesendet...</span>
|
||||
<span v-else>Nachricht senden</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
const form = reactive({
|
||||
name: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
message: ''
|
||||
})
|
||||
|
||||
const isSubmitting = ref(false)
|
||||
const submitSuccess = ref(false)
|
||||
const submitError = ref('')
|
||||
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
isSubmitting.value = true
|
||||
submitError.value = ''
|
||||
|
||||
const response = await fetch('/api/mail', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: form.name,
|
||||
email: form.email,
|
||||
telephone: form.phone || undefined, // Send undefined if empty to match optional schema
|
||||
text: form.message
|
||||
})
|
||||
})
|
||||
|
||||
if(response.status !== 200){
|
||||
throw new Error('Bei der Kommunikation mit dem Server ist ein Fehler aufgetreten.')
|
||||
}
|
||||
const result = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(result.error || 'Fehler beim Senden der Nachricht')
|
||||
}
|
||||
|
||||
// Clear form on success
|
||||
form.name = ''
|
||||
form.email = ''
|
||||
form.phone = ''
|
||||
form.message = ''
|
||||
|
||||
submitSuccess.value = true
|
||||
setTimeout(() => {
|
||||
submitSuccess.value = false
|
||||
}, 5000) // Hide success message after 5 seconds
|
||||
|
||||
} catch (error) {
|
||||
submitError.value = error instanceof Error ? error.message : 'Ein unbekannter Fehler ist aufgetreten'
|
||||
} finally {
|
||||
isSubmitting.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.phone-number {
|
||||
color: var(--highlight-color);
|
||||
}
|
||||
</style>
|
||||
30
docs/.vuepress/components/ContentSection.vue
Normal file
30
docs/.vuepress/components/ContentSection.vue
Normal file
@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<section :id="id" :class="[backgroundColor]">
|
||||
<div class="content-width">
|
||||
<div class="py-16">
|
||||
<h1>{{ title }}</h1>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ContentSection',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default: 'bg-white'
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
34
docs/.vuepress/components/Footer.vue
Normal file
34
docs/.vuepress/components/Footer.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<footer class="bg-[#22596c] text-white py-8">
|
||||
<div class="content-width mx-auto px-4 md:px-6">
|
||||
<div class="flex flex-col md:flex-row justify-between items-center">
|
||||
<div class="mb-4 md:mb-0">
|
||||
<p class="text-sm">© {{ currentYear }} CC BY IT4C.dev & Autoren</p>
|
||||
</div>
|
||||
<div class="flex flex-col sm:flex-row items-center gap-4 sm:gap-6">
|
||||
<a href="/impressum.html" class="!text-white hover:!text-gray-300 hover:!underline text-sm transition-colors">
|
||||
Impressum
|
||||
</a>
|
||||
<a href="https://github.com/IT4Change" target="_blank" rel="noopener noreferrer" class="!text-white hover:!text-gray-300 hover:!underline flex items-center gap-2 text-sm transition-colors">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-github">
|
||||
<path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"></path>
|
||||
<path d="M9 18c-4.51 2-5-2-7-2"></path>
|
||||
</svg>
|
||||
GitHub
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'FooterSection',
|
||||
computed: {
|
||||
currentYear() {
|
||||
return new Date().getFullYear();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
25
docs/.vuepress/components/ProcessStep.vue
Normal file
25
docs/.vuepress/components/ProcessStep.vue
Normal file
@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<div class="grid grid-cols-12 items-start mb-16">
|
||||
<div class="col-span-3 text-right pr-8">
|
||||
<span class="text-6xl font-bold highlight-number">{{ number.padStart(2, '0') }}</span>
|
||||
</div>
|
||||
<div class="col-span-9 pt-4">
|
||||
<h3 class="text-xl font-semibold mb-2">{{ title }}</h3>
|
||||
<p class="text-gray-600">{{ description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
number: string
|
||||
title: string
|
||||
description: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.highlight-number {
|
||||
color: var(--highlight-color);
|
||||
}
|
||||
</style>
|
||||
35
docs/.vuepress/components/ProjectCard.vue
Normal file
35
docs/.vuepress/components/ProjectCard.vue
Normal file
@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<a :href="href">
|
||||
<div class="border border-gray-300 rounded-lg p-6">
|
||||
<img :src="image" :alt="title" class="rounded-lg mb-4 w-full h-48 object-cover">
|
||||
<h3 class="text-xl font-semibold mb-2">{{ title }}</h3>
|
||||
<p class="text-gray-600 mb-4">{{ description }}</p>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span
|
||||
v-for="tag in tags"
|
||||
:key="tag"
|
||||
class="tag px-3 py-1 rounded-full text-sm"
|
||||
>
|
||||
{{ tag }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
title: string
|
||||
description: string
|
||||
image: string
|
||||
tags: string[]
|
||||
href: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.tag {
|
||||
color: var(--highlight-color);
|
||||
background: var(--highlight-color-light);
|
||||
}
|
||||
</style>
|
||||
15
docs/.vuepress/components/ServiceCard.vue
Normal file
15
docs/.vuepress/components/ServiceCard.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div class="p-6 border border-gray-300 rounded-lg">
|
||||
<h3 class="text-xl font-semibold mb-4">{{ title }}</h3>
|
||||
<ul class="space-y-2 text-gray-600">
|
||||
<li v-for="item in items" :key="item">{{ item }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
title: string
|
||||
items: string[]
|
||||
}>()
|
||||
</script>
|
||||
40
docs/.vuepress/components/TeamMember.vue
Normal file
40
docs/.vuepress/components/TeamMember.vue
Normal file
@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<a
|
||||
:href="profileUrl"
|
||||
class="block text-center group transition-transform duration-200 hover:-translate-y-2 active:translate-y-0"
|
||||
>
|
||||
<div class="relative w-48 h-48 mx-auto mb-4">
|
||||
<!-- Image container to control scaling bounds -->
|
||||
<img
|
||||
:src="image"
|
||||
:alt="name"
|
||||
class="rounded-full w-full h-full object-cover grayscale transition-all duration-200 transform
|
||||
group-hover:scale-[1.05]"
|
||||
>
|
||||
<!-- Overlay mit highlight-color-light Variable -->
|
||||
<div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[115%] h-[115%]
|
||||
rounded-full overlay-bg opacity-0 group-hover:opacity-25 transition-opacity duration-200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="font-semibold text-gray-900 transition-colors duration-200 group-hover:text-gray-600">
|
||||
{{ name }}
|
||||
</h4>
|
||||
<p class="text-sm text-gray-600">{{ role }}</p>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
name: string
|
||||
role: string
|
||||
image: string
|
||||
profileUrl: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.overlay-bg {
|
||||
background-color: var(--highlight-color-light);
|
||||
}
|
||||
</style>
|
||||
@ -3,12 +3,19 @@ import Imagemin from 'vuepress-plugin-imagemin'
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import meta from './config/meta'
|
||||
import theme from './config/theme'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
|
||||
export default defineUserConfig({
|
||||
lang: 'de-DE',
|
||||
...meta,
|
||||
theme,
|
||||
bundler: viteBundler({}),
|
||||
bundler: viteBundler({
|
||||
viteOptions: {
|
||||
plugins: [
|
||||
tailwindcss(),
|
||||
]
|
||||
}
|
||||
}),
|
||||
plugins: [
|
||||
Imagemin({
|
||||
gifsicle: {
|
||||
@ -38,5 +45,4 @@ export default defineUserConfig({
|
||||
},
|
||||
}),
|
||||
],
|
||||
|
||||
})
|
||||
@ -1,7 +1,9 @@
|
||||
import { HeadConfig } from "vuepress";
|
||||
|
||||
export default {
|
||||
title: 'IT Team for Change',
|
||||
title: 'IT4C',
|
||||
description: 'IT4C.dev stellt das IT Team for Change, seine angewandte Philosophie und Projekte vor.',
|
||||
head: [
|
||||
['meta', {name: 'viewport', content: 'width=device-width,initial-scale=1'}]
|
||||
],
|
||||
] as HeadConfig[],
|
||||
}
|
||||
@ -22,9 +22,14 @@ export default hopeTheme({
|
||||
],
|
||||
sidebar: [
|
||||
{
|
||||
text: 'IT4C',
|
||||
text: 'Startseite',
|
||||
link: '/',
|
||||
collapsible: false,
|
||||
},
|
||||
{
|
||||
text: 'IT4C',
|
||||
link: '/it4c',
|
||||
collapsible: false,
|
||||
children: [
|
||||
'/historie',
|
||||
'/kontakt'
|
||||
12
docs/.vuepress/layouts/BlankLayout.vue
Normal file
12
docs/.vuepress/layouts/BlankLayout.vue
Normal file
@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<div class="theme-container">
|
||||
<Content />
|
||||
<Footer />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'BlankLayout'
|
||||
}
|
||||
</script>
|
||||
26
docs/.vuepress/styles/index.scss
Normal file
26
docs/.vuepress/styles/index.scss
Normal file
@ -0,0 +1,26 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&family=Source+Sans+3:wght@400;500;600&display=swap');
|
||||
|
||||
:root {
|
||||
--content-width: 1160px;
|
||||
|
||||
--font-family: 'Source Sans 3', sans-serif;
|
||||
--font-family-heading: 'Montserrat', sans-serif;
|
||||
|
||||
--highlight-color: #3894b3;
|
||||
--highlight-color-light: #a5e3f7;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: var(--font-family-heading);
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
border-bottom: none;
|
||||
padding-bottom: 2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.content-width {
|
||||
max-width: var(--content-width);
|
||||
margin: 0 auto;
|
||||
padding: 0 2.5rem;
|
||||
}
|
||||
0
docs/.vuepress/styles/main.css
Normal file
0
docs/.vuepress/styles/main.css
Normal file
BIN
docs/images/hero-bg-desktop.jpg
Normal file
BIN
docs/images/hero-bg-desktop.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 380 KiB |
BIN
docs/images/hero-bg-mobile.jpg
Normal file
BIN
docs/images/hero-bg-mobile.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 150 KiB |
276
docs/index.md
276
docs/index.md
@ -1,38 +1,258 @@
|
||||
# IT4C
|
||||
---
|
||||
layout: BlankLayout
|
||||
---
|
||||
|
||||
**IT Team for Change** (IT4C) ist ein Team von Softwareentwicklern, das gemeinsam Software entwickelt. Unser Fokus liegt auf Out-of-the-Box-Projekten und disruptiver Ziviltechnik, um zum unvermeidlichen Wandel unserer Gesellschaft beizutragen.
|
||||
<section class="full-width-section h-screen relative">
|
||||
<!-- Desktop background image -->
|
||||
<img
|
||||
src="/images/hero-bg-desktop.jpg"
|
||||
alt="Softwareentwicklung für eine bessere Welt"
|
||||
class="w-full h-screen object-cover hidden md:block"
|
||||
/>
|
||||
|
||||
Wir glauben an einen Arbeitsprozess, der genau das richtige Maß an Autorität hat, um vernünftige Entscheidungen zu treffen, uns zu koordinieren und somit unsere Ziele zu erreichen. Die Leitung kann je nach Fachwissen und Verfügbarkeit zwischen den Teammitgliedern wechseln. Außerdem glauben wir, dass jeder, der seine Arbeit gerne macht, effektiver ist, als wenn er dazu gezwungen wird. Wir stellen sicher, dass jedes Mitglied die größtmögliche Freiheit hat, wie es arbeiten möchte.
|
||||
<!-- Desktop gradient -->
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-[#22596c]/100 via-[#22596c]/80 to-transparent dark:from-[#22596c]/100 dark:via-[#22596c]/80 dark:to-transparent hidden md:block" style="width: 65%;"></div>
|
||||
|
||||
Wir sind ein Team, das über ganz Europa verteilt ist und manchmal sogar darüber hinaus. Der Kern des Teams arbeitet seit 2019 zusammen - siehe [Historie](./historie.md). Unser gemeinsamer Nenner neben der Liebe zu sozialen Projekten und der Computertechnologie ist die deutsche Sprache, auch wenn die meiste professionelle Arbeit auf Englisch stattfindet.
|
||||
<div class="w-full h-screen md:hidden relative overflow-hidden">
|
||||
<!-- Mobile background image -->
|
||||
<img
|
||||
src="/images/hero-bg-mobile.jpg"
|
||||
alt="Softwareentwicklung für eine bessere Welt"
|
||||
class="absolute top-0 left-0 w-full h-auto object-cover max-h-none"
|
||||
style="min-width: 100%;"
|
||||
/>
|
||||
</div>
|
||||
|
||||
Eines unserer Prinzipien, um Projekte nicht unwartbar zu machen, ist die Verbreitung von Wissen innerhalb des Teams und die Rekrutierung neuer Mitglieder, die lernen wollen, wie wir Softwareentwicklung betreiben. Wir leben den agilen Prozess mit kurzen Release-Zyklen und wöchentlichen Feedback-Schleifen, um sicherzustellen, dass unsere Software tatsächlich die Bedürfnisse unserer Auftraggeber und Nutzer erfüllt.
|
||||
<!-- Mobile gradient -->
|
||||
<div class="absolute left-0 right-0 bottom-0 md:hidden bg-gradient-to-t from-[#22596c]/100 via-[#22596c]/100 via-[#22596c]/90 to-transparent dark:from-[#22596c]/100 dark:via-[#22596c]/100 dark:via-[#22596c]/90 dark:to-transparent"
|
||||
style="height: 70vh;">
|
||||
</div>
|
||||
|
||||
## Projekte
|
||||
<!-- Content area -->
|
||||
<div class="absolute inset-0 flex flex-col md:justify-start md:pt-45 justify-end pb-16">
|
||||
<div class="content-width mx-auto px-4 md:px-6">
|
||||
<!-- Für Desktop: Normal positioniert mit margin-top -->
|
||||
<!-- Für Mobile: Am unteren Rand fixiert ohne margin -->
|
||||
<div class="w-full md:w-3/5 lg:w-1/2 z-10 md:mt-0 relative">
|
||||
<div
|
||||
role="heading"
|
||||
aria-level="1"
|
||||
class="text-3xl md:text-4xl lg:text-5xl mb-6 text-white font-montserrat leading-tight text-shadow"
|
||||
>
|
||||
Softwareentwicklung für eine bessere Welt
|
||||
</div>
|
||||
<p
|
||||
class="text-xl md:text-2xl text-white font-sourcesans mb-8 max-w-2xl text-shadow-sm"
|
||||
>
|
||||
Wir sind Softwareentwickler, die deine alternative Vision verstehen und umsetzen. Mit technischer Expertise und persönlicher Betreuung unterstützen wir Projekte, die Positives bewirken.
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row gap-4">
|
||||
<a
|
||||
href="#kontakt"
|
||||
class="hero-button hero-button-primary px-6 py-3 bg-[#ececec] !text-black rounded-full font-medium text-center shadow-md no-underline relative overflow-hidden"
|
||||
>
|
||||
<span class="relative z-10">Projekt starten</span>
|
||||
</a>
|
||||
<a
|
||||
href="#leistungen"
|
||||
class="hero-button hero-button-secondary px-6 py-3 bg-black/20 !text-white rounded-full font-medium text-center border border-white shadow-md no-underline relative overflow-hidden"
|
||||
>
|
||||
<span class="relative z-10">Unsere Leistungen</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Einige Projekte, auf die wir stolz sind:
|
||||
<ContentSection id="leistungen" title="Leistungen">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 my-8">
|
||||
<ServiceCard
|
||||
title="Webentwicklung"
|
||||
:items="['Frontend', 'Responsive Design', 'Barrierefreiheit', 'Backend']"
|
||||
/>
|
||||
<ServiceCard
|
||||
title="Hosting"
|
||||
:items="['Wordpress', 'Ocelot.social', 'Zugeschnittene Lösungen', 'Nachhaltige Serverinfrastrukturen']"
|
||||
/>
|
||||
<ServiceCard
|
||||
title="Mobile Anwendungen"
|
||||
:items="['Android', 'iOS', 'PWA']"
|
||||
/>
|
||||
<ServiceCard
|
||||
title="Beratung & Betreuung"
|
||||
:items="['Systemarchitektur', 'DevOps & Prozessbegleitung', 'Monitoring & Security', 'Technische Konzeption', 'Agiles Projektmanagement', 'Nachhaltigkeitsanalyse']"
|
||||
/>
|
||||
<ServiceCard
|
||||
title="Software-Entwicklung"
|
||||
:items="['API-Entwicklung', 'Datenbank-Design', 'Performance-Optimierung', 'Deployment-Automatisierung', 'Code-Qualität & Testing']"
|
||||
/>
|
||||
</div>
|
||||
</ContentSection>
|
||||
|
||||
- [DEMOCRACY App](./projekte/democracy.app.md)
|
||||
- Human-Connection <!-- [Human-Connection](./projekte/human-connection.md)-->
|
||||
- [Ocelot.social](./projekte/ocelot.social.md)
|
||||
- wir.social <!-- [wir.social](./projekte/wir.social.md) -->
|
||||
- sender.fm <!-- [sender.fm](./projekte/sender.fm.md) -->
|
||||
- Yunite.me <!--[Yunite.me](./projekte/yunite.me.md) -->
|
||||
- [Gradido](./projekte/gradido.md)
|
||||
- [DreamMall](./projekte/dreammall.md)
|
||||
<ContentSection id="team" title="Team & Werte" backgroundColor="bg-gray-50">
|
||||
<p>Wir glauben an die Kraft der Technologie für positiven Wandel. Unser diverses Team verbindet technische Expertise mit nachhaltigem Denken und sozialer Verantwortung.</p>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6 mt-10">
|
||||
<TeamMember
|
||||
name="Hannes"
|
||||
role="Backend"
|
||||
profileUrl="/team/hannes-heine.html"
|
||||
image="/images/portrait/hannes-heine.jpg"
|
||||
/>
|
||||
<TeamMember
|
||||
name="Mathias"
|
||||
role="Testing"
|
||||
profileUrl="/team/mathias-lenz.html"
|
||||
image="/images/portrait/ml-portrait.jpg"
|
||||
/>
|
||||
<TeamMember
|
||||
name="Max"
|
||||
role="Frontend"
|
||||
profileUrl="/team/maximilian-harz.html"
|
||||
image="/images/portrait/max.jpg"
|
||||
/>
|
||||
<TeamMember
|
||||
name="Moriz"
|
||||
role="Backend"
|
||||
profileUrl="/team/moriz-wahl.html"
|
||||
image="/images/portrait/moriz-wahl.jpg"
|
||||
/>
|
||||
<TeamMember
|
||||
name="Sebastian"
|
||||
role="Frontend"
|
||||
profileUrl="/team/sebastian-stein.html"
|
||||
image="/images/portrait/sebastian-stein.jpg"
|
||||
/>
|
||||
<TeamMember
|
||||
name="Ulf"
|
||||
role="Backend, Hosting"
|
||||
profileUrl="/team/ulf-gebhardt.html"
|
||||
image="/images/portrait/ulf-gebhardt.jpg"
|
||||
/>
|
||||
<TeamMember
|
||||
name="Wolfgang"
|
||||
role="Backend"
|
||||
profileUrl="/team/wolfgang-huss.html"
|
||||
image="/images/portrait/Wolfgang_Huss.jpeg"
|
||||
/>
|
||||
</div>
|
||||
</ContentSection>
|
||||
|
||||
## Mitglieder und Mitarbeiter
|
||||
<ContentSection id="referenzen" title="Referenzen">
|
||||
<div class="grid md:grid-cols-2 gap-8">
|
||||
<ProjectCard
|
||||
title="Ocelot.Social"
|
||||
description="Ocelot.social ist eine Open-Source Alternative für soziale Netzwerke wie Facebook, Instagram oder TikTok"
|
||||
image="images/projects/ocelot-newsfeed.png"
|
||||
:tags="['Social Media']"
|
||||
href="/projekte/ocelot.social"
|
||||
/>
|
||||
<ProjectCard
|
||||
title="DreamMall.earth"
|
||||
description="DreamMall.earth ist eine Video & Projekt Management Plattform,"
|
||||
image="/images/projects/dreammall.png"
|
||||
:tags="['Video-Konferenz', 'Projekt Management']"
|
||||
href="/projekte/dreammall"
|
||||
/>
|
||||
</div>
|
||||
</ContentSection>
|
||||
|
||||
- [Alexander Friedland](./team/alexander-friedland.md)
|
||||
- [Hannes Heine](./team/hannes-heine.md)
|
||||
- [Mathias Lenz](./team/mathias-lenz.md)
|
||||
- [Maximilian Harz](./team/maximilian-harz.md)
|
||||
- [Moriz Wahl](./team/moriz-wahl.md)
|
||||
- [Sebastian Stein](./people/sebastian-stein.md)
|
||||
- [Ulf Gebhardt](./team/ulf-gebhardt.md)
|
||||
- [Wolfgang Huß](./team/wolfgang-huss.md)
|
||||
<ContentSection id="prozess" title="Unser Prozess" backgroundColor="bg-gray-50">
|
||||
<ProcessStep
|
||||
number="1"
|
||||
title="Kennenlernen & Vision"
|
||||
description="Persönliches Gespräch und detaillierte Bedarfsanalyse"
|
||||
/>
|
||||
<ProcessStep
|
||||
number="2"
|
||||
title="Agile Entwicklung"
|
||||
description="Technische Konzeption und iterative Umsetzung mit kontinuierlichem Feedback und automatisierten Tests"
|
||||
/>
|
||||
<ProcessStep
|
||||
number="3"
|
||||
title="Launch"
|
||||
description="Deployment und Übergabe mit ausführlicher Dokumentation"
|
||||
/>
|
||||
<ProcessStep
|
||||
number="4"
|
||||
title="Support"
|
||||
description="Langfristige Betreuung und Weiterentwicklung"
|
||||
/>
|
||||
</ContentSection>
|
||||
|
||||
<!-- ## Organisationen -->
|
||||
<!-- textlint-disable period-in-list-item -->
|
||||
<!-- - busFaktor() e.V. -->
|
||||
<!-- textlint-enable period-in-list-item -->
|
||||
<ContentSection id="kontakt" title="Kontakt">
|
||||
<ContactForm />
|
||||
</ContentSection>
|
||||
|
||||
|
||||
<style>
|
||||
@import "tailwindcss";
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: 'Montserrat', sans-serif !important;
|
||||
}
|
||||
|
||||
.font-montserrat {
|
||||
font-family: 'Montserrat', sans-serif !important;
|
||||
}
|
||||
|
||||
.font-sourcesans {
|
||||
font-family: 'Source Sans 3', sans-serif !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.text-shadow {
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
||||
|
||||
&-sm {
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.hero {
|
||||
&-title {
|
||||
font-family: 'Montserrat', sans-serif !important;
|
||||
font-weight: 700 !important;
|
||||
margin: 0 0 1.5rem 0 !important;
|
||||
line-height: 1.1 !important;
|
||||
}
|
||||
|
||||
&-button {
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border-radius: 9999px;
|
||||
opacity: 0;
|
||||
transform: scale(0.5);
|
||||
transition: transform 0.5s ease, opacity 0.5s ease;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
&:hover::after {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
&-primary::after {
|
||||
background: radial-gradient(circle, rgba(253, 224, 71, 0.3) 0%, rgba(253, 224, 71) 70%, rgba(253, 224, 71) 100%);
|
||||
}
|
||||
|
||||
&-secondary::after {
|
||||
background: radial-gradient(circle, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.2) 70%, rgba(0, 0, 0, 0) 100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
38
docs/it4c.md
Normal file
38
docs/it4c.md
Normal file
@ -0,0 +1,38 @@
|
||||
# IT4C
|
||||
|
||||
**IT Team for Change** (IT4C) ist ein Team von Softwareentwicklern, das gemeinsam Software entwickelt. Unser Fokus liegt auf Out-of-the-Box-Projekten und disruptiver Ziviltechnik, um zum unvermeidlichen Wandel unserer Gesellschaft beizutragen.
|
||||
|
||||
Wir glauben an einen Arbeitsprozess, der genau das richtige Maß an Autorität hat, um vernünftige Entscheidungen zu treffen, uns zu koordinieren und somit unsere Ziele zu erreichen. Die Leitung kann je nach Fachwissen und Verfügbarkeit zwischen den Teammitgliedern wechseln. Außerdem glauben wir, dass jeder, der seine Arbeit gerne macht, effektiver ist, als wenn er dazu gezwungen wird. Wir stellen sicher, dass jedes Mitglied die größtmögliche Freiheit hat, wie es arbeiten möchte.
|
||||
|
||||
Wir sind ein Team, das über ganz Europa verteilt ist und manchmal sogar darüber hinaus. Der Kern des Teams arbeitet seit 2019 zusammen - siehe [Historie](./historie.md). Unser gemeinsamer Nenner neben der Liebe zu sozialen Projekten und der Computertechnologie ist die deutsche Sprache, auch wenn die meiste professionelle Arbeit auf Englisch stattfindet.
|
||||
|
||||
Eines unserer Prinzipien, um Projekte nicht unwartbar zu machen, ist die Verbreitung von Wissen innerhalb des Teams und die Rekrutierung neuer Mitglieder, die lernen wollen, wie wir Softwareentwicklung betreiben. Wir leben den agilen Prozess mit kurzen Release-Zyklen und wöchentlichen Feedback-Schleifen, um sicherzustellen, dass unsere Software tatsächlich die Bedürfnisse unserer Auftraggeber und Nutzer erfüllt.
|
||||
|
||||
## Projekte
|
||||
|
||||
Einige Projekte, auf die wir stolz sind:
|
||||
|
||||
- [DEMOCRACY App](./projekte/democracy.app.md)
|
||||
- Human-Connection <!-- [Human-Connection](./projekte/human-connection.md)-->
|
||||
- [Ocelot.social](./projekte/ocelot.social.md)
|
||||
- wir.social <!-- [wir.social](./projekte/wir.social.md) -->
|
||||
- sender.fm <!-- [sender.fm](./projekte/sender.fm.md) -->
|
||||
- Yunite.me <!--[Yunite.me](./projekte/yunite.me.md) -->
|
||||
- [Gradido](./projekte/gradido.md)
|
||||
- [DreamMall](./projekte/dreammall.md)
|
||||
|
||||
## Mitglieder und Mitarbeiter
|
||||
|
||||
- [Alexander Friedland](./team/alexander-friedland.md)
|
||||
- [Hannes Heine](./team/hannes-heine.md)
|
||||
- [Mathias Lenz](./team/mathias-lenz.md)
|
||||
- [Maximilian Harz](./team/maximilian-harz.md)
|
||||
- [Moriz Wahl](./team/moriz-wahl.md)
|
||||
- [Sebastian Stein](./people/sebastian-stein.md)
|
||||
- [Ulf Gebhardt](./team/ulf-gebhardt.md)
|
||||
- [Wolfgang Huß](./team/wolfgang-huss.md)
|
||||
|
||||
<!-- ## Organisationen -->
|
||||
<!-- textlint-disable period-in-list-item -->
|
||||
<!-- - busFaktor() e.V. -->
|
||||
<!-- textlint-enable period-in-list-item -->
|
||||
1588
package-lock.json
generated
1588
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -20,10 +20,12 @@
|
||||
},
|
||||
"homepage": "https://github.com/IT4Change/IT4C.dev#readme",
|
||||
"devDependencies": {
|
||||
"@tailwindcss/vite": "^4.0.5",
|
||||
"@textlint-rule/textlint-rule-no-unmatched-pair": "^2.0.4",
|
||||
"@vuepress/bundler-vite": "^2.0.0-rc.20",
|
||||
"@vuepress/plugin-slimsearch": "^2.0.0-rc.82",
|
||||
"http-server": "^14.1.1",
|
||||
"tailwindcss": "^4.0.5",
|
||||
"textlint": "^14.4.2",
|
||||
"textlint-filter-rule-comments": "^1.2.2",
|
||||
"textlint-rule-apostrophe": "^3.0.0",
|
||||
|
||||
11
tailwind.config.ts
Normal file
11
tailwind.config.ts
Normal file
@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
content: [
|
||||
'./docs/**/*.{vue,js,ts,jsx,tsx,md}',
|
||||
'!./**/cache',
|
||||
'!./**/.temp',
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user