feat: update landing page with current screenshots
36
README.md
@@ -21,13 +21,13 @@ I'm a small self-hosted accountant app that can help you deal with invoices, rec
|
|||||||
|
|
||||||
## 👋🏻 Getting Started
|
## 👋🏻 Getting Started
|
||||||
|
|
||||||
TaxHacker is a self-hosted accounting app for freelancers and small businesses who want to save time and automate expences and income tracking with power of GenAI. It can recognise uploaded photos, receipts or PDFs and extract important data (e.g. name, total amount, date, merchant, VAT) and save it as structured transactions to a table. You can also create your own custom fields to extract with your LLM prompts.
|
TaxHacker is a self-hosted accounting app for freelancers, indie-hackers and small businesses who want to save time and automate expences and income tracking with power of GenAI. It can recognise uploaded photos, receipts or PDFs and extract important data (e.g. name, total amount, date, merchant, VAT) and save it as structured transactions to a table. You can also create your own custom fields to extract with your LLM prompts.
|
||||||
|
|
||||||
It supports automatic currency conversion on a day of transaction. Even for crypto!
|
It supports automatic currency conversion on a day of transaction. Even for crypto!
|
||||||
|
|
||||||
Built-in system of filters, support for multiple projects, import-export of transactions for a certain time (along with attached files) and custom categories, allows you to simplify reporting and tax filing.
|
Built-in system of filters, support for multiple projects, import-export of transactions for a certain time (along with attached files) and custom categories, allows you to simplify reporting and tax filing.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
> \[!IMPORTANT]
|
> \[!IMPORTANT]
|
||||||
>
|
>
|
||||||
@@ -37,6 +37,8 @@ Built-in system of filters, support for multiple projects, import-export of tran
|
|||||||
|
|
||||||
### `1` Upload photos or documents to analyze with LLM
|
### `1` Upload photos or documents to analyze with LLM
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
https://github.com/user-attachments/assets/3326d0e3-0bf6-4c39-9e00-4bf0983d9b7a
|
https://github.com/user-attachments/assets/3326d0e3-0bf6-4c39-9e00-4bf0983d9b7a
|
||||||
|
|
||||||
> 🎥 [Watch the video](https://github.com/user-attachments/assets/3326d0e3-0bf6-4c39-9e00-4bf0983d9b7a)
|
> 🎥 [Watch the video](https://github.com/user-attachments/assets/3326d0e3-0bf6-4c39-9e00-4bf0983d9b7a)
|
||||||
@@ -53,7 +55,7 @@ TaxHacker recognizes a wide variety of documents including store receipts, resta
|
|||||||
|
|
||||||
### `2` Multi-currency support with automatic conversion (even for crypto)
|
### `2` Multi-currency support with automatic conversion (even for crypto)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
TaxHacker automatically converts foreign currencies and even knows the historical exchange rates on the invoice date.
|
TaxHacker automatically converts foreign currencies and even knows the historical exchange rates on the invoice date.
|
||||||
|
|
||||||
@@ -62,9 +64,20 @@ TaxHacker automatically converts foreign currencies and even knows the historica
|
|||||||
- Historical exchange rate lookup for past transactions
|
- Historical exchange rate lookup for past transactions
|
||||||
- Support for over 170 world currencies and 14 popular cryptocurrencies (BTC, ETC, LTC, DOT, etc)!
|
- Support for over 170 world currencies and 14 popular cryptocurrencies (BTC, ETC, LTC, DOT, etc)!
|
||||||
|
|
||||||
### `3` Customize any LLM prompt
|
### `3` Create custom fields, projects, categories
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
Adapt TaxHacker to your specific tracking needs. You can create new fields, projects or categories to extract additional information from documents. For example, if you need to save emails, addresses, and any custom information into separate fields, you can do it. Custom fields will be available when exporting too.
|
||||||
|
|
||||||
|
- Create unlimited custom fields for transaction tracking
|
||||||
|
- Automatically extract custom field data using AI
|
||||||
|
- Include custom fields in exports and reports
|
||||||
|
- Create new categories or projects to organise your transactions and filter by them
|
||||||
|
|
||||||
|
### `4` `Customize any LLM prompt
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
You can customize LLM Prompts for built-in fields, categories, and projects, as well as modify global templates in the application settings. This allows to customize the quality of recognizing specific things to your specific use-cases.
|
You can customize LLM Prompts for built-in fields, categories, and projects, as well as modify global templates in the application settings. This allows to customize the quality of recognizing specific things to your specific use-cases.
|
||||||
|
|
||||||
@@ -75,20 +88,9 @@ You can customize LLM Prompts for built-in fields, categories, and projects, as
|
|||||||
|
|
||||||
The whole extraction process is under your contoll all the time!
|
The whole extraction process is under your contoll all the time!
|
||||||
|
|
||||||
### `4` Create custom fields, projects, categories
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Adapt TaxHacker to your specific tracking needs. You can create new fields, projects or categories to extract additional information from documents. For example, if you need to save emails, addresses, and any custom information into separate fields, you can do it. Custom fields will be available when exporting too.
|
|
||||||
|
|
||||||
- Create unlimited custom fields for transaction tracking
|
|
||||||
- Automatically extract custom field data using AI
|
|
||||||
- Include custom fields in exports and reports
|
|
||||||
- Create new categories or projects to organise your transactions and filter by them
|
|
||||||
|
|
||||||
### `5` Flexible data filtering and export
|
### `5` Flexible data filtering and export
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Once all documents have been uploaded and analyzed, you can view, filter and export your transaction history.
|
Once all documents have been uploaded and analyzed, you can view, filter and export your transaction history.
|
||||||
|
|
||||||
|
|||||||
@@ -25,13 +25,13 @@ export default function LandingPage() {
|
|||||||
<div className="flex gap-1 md:gap-4 text-xs md:text-sm">
|
<div className="flex gap-1 md:gap-4 text-xs md:text-sm">
|
||||||
<Link
|
<Link
|
||||||
href="/enter"
|
href="/enter"
|
||||||
className="font-medium px-4 py-2 rounded-full border-2 border-gradient-to-r from-pink-300 to-indigo-300 hover:from-pink-400 hover:to-indigo-400 bg-white/80 hover:bg-white transition-all duration-300 hover:scale-105"
|
className="cursor-pointer font-medium px-4 py-2 rounded-full border-2 border-gradient-to-r from-pink-300 to-indigo-300 hover:from-pink-400 hover:to-indigo-400 bg-white/80 hover:bg-white transition-all duration-300 hover:scale-105"
|
||||||
>
|
>
|
||||||
Log In
|
Log In
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
href="/cloud"
|
href="/cloud"
|
||||||
className="font-medium bg-gradient-to-r from-pink-600 to-indigo-600 text-white px-4 py-2 rounded-full hover:from-pink-700 hover:to-indigo-700 transition-all duration-300 hover:scale-105 shadow-lg hover:shadow-xl"
|
className="cursor-pointer font-medium bg-gradient-to-r from-pink-600 to-indigo-600 text-white px-4 py-2 rounded-full hover:from-pink-700 hover:to-indigo-700 transition-all duration-300 hover:scale-105 shadow-lg hover:shadow-xl"
|
||||||
>
|
>
|
||||||
Sign Up
|
Sign Up
|
||||||
</Link>
|
</Link>
|
||||||
@@ -48,14 +48,14 @@ export default function LandingPage() {
|
|||||||
|
|
||||||
<div className="max-w-7xl mx-auto relative z-10">
|
<div className="max-w-7xl mx-auto relative z-10">
|
||||||
<div className="text-center mb-12">
|
<div className="text-center mb-12">
|
||||||
<div className="inline-block px-6 py-3 rounded-full bg-gradient-to-r from-pink-600 to-indigo-600 text-white text-sm font-medium mb-6 shadow-lg hover:shadow-xl transition-all duration-300 hover:scale-105">
|
<div className="inline-block px-6 py-3 rounded-full border-2 border-pink-600/50 text-sm font-medium mb-6 shadow-lg hover:shadow-xl transition-all duration-300">
|
||||||
🚀 Under Active Development
|
🚀 Under Active Development
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-5xl font-bold tracking-tight sm:text-6xl mb-6 bg-gradient-to-r from-gray-900 via-pink-700 to-indigo-700 bg-clip-text text-transparent pb-2">
|
<h1 className="text-5xl font-bold tracking-tight sm:text-6xl mb-6 bg-gradient-to-r from-gray-900 via-pink-700 to-indigo-700 bg-clip-text text-transparent pb-2">
|
||||||
Let AI finally care about your taxes, scan your receipts and analyze your expenses
|
Let AI finally care about your taxes, scan your receipts and analyze your expenses
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-xl text-gray-700 mb-8 max-w-2xl mx-auto font-medium">
|
<p className="text-xl text-gray-700 mb-8 max-w-2xl mx-auto font-medium">
|
||||||
A self-hosted accounting app crafted with love for freelancers and small businesses
|
Self-hosted accounting app crafted for freelancers, indie-hackers and small businesses
|
||||||
</p>
|
</p>
|
||||||
<div className="flex gap-4 justify-center text-sm md:text-lg">
|
<div className="flex gap-4 justify-center text-sm md:text-lg">
|
||||||
<Link
|
<Link
|
||||||
@@ -65,18 +65,18 @@ export default function LandingPage() {
|
|||||||
Get Started ✨
|
Get Started ✨
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
href="mailto:me@vas3k.ru"
|
href="mailto:me@vas3k.com"
|
||||||
className="px-8 py-4 border-2 border-gradient-to-r from-pink-300 to-indigo-300 text-gray-800 font-bold rounded-full hover:bg-gradient-to-r hover:from-pink-50 hover:to-indigo-50 transition-all duration-300 hover:scale-105 bg-white/80"
|
className="px-8 py-4 border-2 border-gradient-to-r from-pink-300 to-indigo-300 text-gray-800 font-bold rounded-full hover:bg-gradient-to-r hover:from-pink-50 hover:to-indigo-50 transition-all duration-300 hover:scale-105 bg-white/80"
|
||||||
>
|
>
|
||||||
Contact Us 💌
|
Contact Us 💌
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-pink-200 to-indigo-200 hover:scale-105 transition-all duration-500 group">
|
<div className="relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-pink-200 to-indigo-200">
|
||||||
<div className="absolute inset-0 bg-gradient-to-b from-pink-500/10 via-purple-500/10 to-indigo-500/10 z-10 group-hover:from-pink-500/20 group-hover:to-indigo-500/20 transition-all duration-500" />
|
<div className="absolute inset-0 bg-gradient-to-b from-pink-500/5 via-purple-500/5 to-indigo-500/10 z-10" />
|
||||||
<video className="w-full h-auto" autoPlay loop muted playsInline poster="/landing/title.webp">
|
<video className="w-full h-auto" autoPlay loop muted playsInline poster="/landing/ai-scanner-big.webp">
|
||||||
<source src="/landing/video.mp4" type="video/mp4" />
|
<source src="/landing/video.mp4" type="video/mp4" />
|
||||||
<Image src="/landing/title.webp" alt="TaxHacker" width={1980} height={1224} priority />
|
<Image src="/landing/ai-scanner-big.webp" alt="TaxHacker" width={1728} height={1080} priority />
|
||||||
</video>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -92,7 +92,7 @@ export default function LandingPage() {
|
|||||||
F∗ck Taxes
|
F∗ck Taxes
|
||||||
</span>
|
</span>
|
||||||
<span className="text-4xl font-bold bg-gradient-to-r from-gray-900 to-gray-600 bg-clip-text text-transparent">
|
<span className="text-4xl font-bold bg-gradient-to-r from-gray-900 to-gray-600 bg-clip-text text-transparent">
|
||||||
TaxHacker can save you time, money and nerves
|
TaxHacker saves you time, money and nerves
|
||||||
</span>
|
</span>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
@@ -113,16 +113,20 @@ export default function LandingPage() {
|
|||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-blue-600 mr-3 text-lg">✨</span>
|
<span className="text-blue-600 mr-3 text-lg">✨</span>
|
||||||
Extract key information like dates, amounts, and vendors
|
Extract key information like dates, items, and vendors
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-blue-600 mr-3 text-lg">✨</span>
|
<span className="text-blue-600 mr-3 text-lg">✨</span>
|
||||||
Works with any language, format and photo quality
|
Works with any language and any photo quality
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-blue-600 mr-3 text-lg">✨</span>
|
<span className="text-blue-600 mr-3 text-lg">✨</span>
|
||||||
Automatically organize everything into a structured database
|
Automatically organize everything into a structured database
|
||||||
</li>
|
</li>
|
||||||
|
<li className="flex items-center">
|
||||||
|
<span className="text-blue-600 mr-3 text-lg">✨</span>
|
||||||
|
Bulk upload and analyze multiple files at once
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-blue-200 to-indigo-200 hover:scale-105 transition-all duration-500">
|
<div className="flex-1 relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-blue-200 to-indigo-200 hover:scale-105 transition-all duration-500">
|
||||||
@@ -137,24 +141,28 @@ export default function LandingPage() {
|
|||||||
💱 Currency Converter
|
💱 Currency Converter
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-green-700 to-emerald-700 bg-clip-text text-transparent">
|
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-green-700 to-emerald-700 bg-clip-text text-transparent">
|
||||||
Automatically convert currencies
|
Automatically convert currencies (even crypto!)
|
||||||
</h3>
|
</h3>
|
||||||
<ul className="space-y-3 text-gray-700">
|
<ul className="space-y-3 text-gray-700">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-green-600 mr-3 text-lg">💰</span>
|
<span className="text-green-600 mr-3 text-lg">💰</span>
|
||||||
Detects foreign currencies and coverts it to yours
|
Detects foreign currencies and converts it to yours
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-green-600 mr-3 text-lg">💰</span>
|
<span className="text-green-600 mr-3 text-lg">💰</span>
|
||||||
Historical exchange rate lookup on a date of transaction
|
Knows historical exchange rates on a date of transaction
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-green-600 mr-3 text-lg">💰</span>
|
<span className="text-green-600 mr-3 text-lg">💰</span>
|
||||||
Support for 170+ world currencies
|
Supports 170+ world currencies
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-green-600 mr-3 text-lg">💰</span>
|
<span className="text-green-600 mr-3 text-lg">💰</span>
|
||||||
Even works with cryptocurrencies (BTC, ETH, LTC, etc.)
|
Works with popular cryptocurrencies (BTC, ETH, LTC, etc.)
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center">
|
||||||
|
<span className="text-green-600 mr-3 text-lg">💰</span>
|
||||||
|
Still allows you to fill it manually
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -170,12 +178,16 @@ export default function LandingPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex-1 min-w-60">
|
<div className="flex-1 min-w-60">
|
||||||
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-pink-500 to-rose-600 text-white text-sm font-bold mb-4 shadow-lg">
|
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-pink-500 to-rose-600 text-white text-sm font-bold mb-4 shadow-lg">
|
||||||
🔍 Filters
|
🔍 Filters & Categories
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-pink-700 to-rose-700 bg-clip-text text-transparent">
|
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-pink-700 to-rose-700 bg-clip-text text-transparent">
|
||||||
Organize expenses and income
|
Organize your transactions using fully customizable categories, projects and fields
|
||||||
</h3>
|
</h3>
|
||||||
<ul className="space-y-3 text-gray-700">
|
<ul className="space-y-3 text-gray-700">
|
||||||
|
<li className="flex items-center">
|
||||||
|
<span className="text-pink-600 mr-3 text-lg">📊</span>
|
||||||
|
Absolute freedom to create custom categories, projects and fields
|
||||||
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-pink-600 mr-3 text-lg">📊</span>
|
<span className="text-pink-600 mr-3 text-lg">📊</span>
|
||||||
Add, edit and manage your transactions
|
Add, edit and manage your transactions
|
||||||
@@ -211,19 +223,23 @@ export default function LandingPage() {
|
|||||||
<ul className="space-y-3 text-gray-700">
|
<ul className="space-y-3 text-gray-700">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-3 text-lg">📄</span>
|
<span className="text-purple-600 mr-3 text-lg">📄</span>
|
||||||
???
|
Advanced invoice generator to create any invoice in any language
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-3 text-lg">📄</span>
|
<span className="text-purple-600 mr-3 text-lg">📄</span>
|
||||||
???
|
Edit any field, even labels and titles
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-3 text-lg">📄</span>
|
<span className="text-purple-600 mr-3 text-lg">📄</span>
|
||||||
???
|
Export invoices to PDF or as transactions
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-3 text-lg">📄</span>
|
<span className="text-purple-600 mr-3 text-lg">📄</span>
|
||||||
???
|
Save invoices as templates to reuse them later
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center">
|
||||||
|
<span className="text-purple-600 mr-3 text-lg">📄</span>
|
||||||
|
Native support for both included and excluded taxes (VAT, GST, etc.)
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -231,20 +247,21 @@ export default function LandingPage() {
|
|||||||
|
|
||||||
{/* Custom Fields & Categories */}
|
{/* Custom Fields & Categories */}
|
||||||
<div className="flex flex-wrap items-center gap-12 mb-20 bg-gradient-to-br from-white via-violet-50/30 to-purple-50/30 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-violet-200 to-purple-200 hover:shadow-2xl transition-all duration-500 group">
|
<div className="flex flex-wrap items-center gap-12 mb-20 bg-gradient-to-br from-white via-violet-50/30 to-purple-50/30 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-violet-200 to-purple-200 hover:shadow-2xl transition-all duration-500 group">
|
||||||
<div className="flex-1 relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-violet-200 to-purple-200 hover:scale-105 transition-all duration-500">
|
|
||||||
<Image src="/landing/custom-llm.webp" alt="Custom LLM promts" width={1800} height={1081} />
|
|
||||||
</div>
|
|
||||||
<div className="flex-1 min-w-60">
|
<div className="flex-1 min-w-60">
|
||||||
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-violet-500 to-purple-600 text-white text-sm font-bold mb-4 shadow-lg">
|
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-violet-500 to-purple-600 text-white text-sm font-bold mb-4 shadow-lg">
|
||||||
🎨 Customization
|
🎨 Control over AI
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-violet-700 to-purple-700 bg-clip-text text-transparent">
|
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-violet-700 to-purple-700 bg-clip-text text-transparent">
|
||||||
Create custom LLM promts to extract anything
|
Write custom LLM promts to extract anything
|
||||||
</h3>
|
</h3>
|
||||||
<ul className="space-y-3 text-gray-700">
|
<ul className="space-y-3 text-gray-700">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-violet-600 mr-3 text-lg">🔧</span>
|
<span className="text-violet-600 mr-3 text-lg">🔧</span>
|
||||||
Create custom fields and categories with your own LLM prompts
|
Expand and improve your TaxHacker instance with custom LLM prompts
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center">
|
||||||
|
<span className="text-violet-600 mr-3 text-lg">🔧</span>
|
||||||
|
Create custom fields and categories and tell AI how to parse them for you
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-violet-600 mr-3 text-lg">🔧</span>
|
<span className="text-violet-600 mr-3 text-lg">🔧</span>
|
||||||
@@ -260,16 +277,16 @@ export default function LandingPage() {
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex-1 relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-violet-200 to-purple-200 hover:scale-105 transition-all duration-500">
|
||||||
|
<Image src="/landing/custom-llm.webp" alt="Custom LLM promts" width={1800} height={1081} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Data Export */}
|
{/* Data Export */}
|
||||||
<div className="flex flex-wrap items-center gap-12 mb-20 bg-gradient-to-br from-white via-orange-50/30 to-amber-50/30 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-orange-200 to-amber-200 hover:shadow-2xl transition-all duration-500 group flex-row-reverse">
|
<div className="flex flex-wrap items-center gap-12 mb-20 bg-gradient-to-br from-white via-orange-50/30 to-amber-50/30 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-orange-200 to-amber-200 hover:shadow-2xl transition-all duration-500 group flex-row-reverse">
|
||||||
<div className="flex-1 relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-orange-200 to-amber-200 hover:scale-105 transition-all duration-500">
|
|
||||||
<Image src="/landing/export.webp" alt="Export" width={1200} height={1081} />
|
|
||||||
</div>
|
|
||||||
<div className="flex-1 min-w-60">
|
<div className="flex-1 min-w-60">
|
||||||
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-orange-500 to-amber-600 text-white text-sm font-bold mb-4 shadow-lg">
|
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-orange-500 to-amber-600 text-white text-sm font-bold mb-4 shadow-lg">
|
||||||
📦 Export
|
📦 Self-hosting & Export
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-orange-700 to-amber-700 bg-clip-text text-transparent">
|
<h3 className="text-2xl font-bold mb-4 bg-gradient-to-r from-orange-700 to-amber-700 bg-clip-text text-transparent">
|
||||||
Your Data — Your Rules
|
Your Data — Your Rules
|
||||||
@@ -277,11 +294,15 @@ export default function LandingPage() {
|
|||||||
<ul className="space-y-3 text-gray-700">
|
<ul className="space-y-3 text-gray-700">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-orange-600 mr-3 text-lg">📤</span>
|
<span className="text-orange-600 mr-3 text-lg">📤</span>
|
||||||
Flexible filters to export your data for tax prep
|
Deploy your own instance of TaxHacker if you want 100% privacy
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-orange-600 mr-3 text-lg">📤</span>
|
<span className="text-orange-600 mr-3 text-lg">📤</span>
|
||||||
Full-text search across documents
|
Export your transactions to CSV for tax prep or any other purpose
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center">
|
||||||
|
<span className="text-orange-600 mr-3 text-lg">📤</span>
|
||||||
|
Full-text search across documents and invoices
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-orange-600 mr-3 text-lg">📤</span>
|
<span className="text-orange-600 mr-3 text-lg">📤</span>
|
||||||
@@ -289,10 +310,14 @@ export default function LandingPage() {
|
|||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-orange-600 mr-3 text-lg">📤</span>
|
<span className="text-orange-600 mr-3 text-lg">📤</span>
|
||||||
Download full data archive to migrate to another service
|
Download full data archive to migrate to another service. We don't take away or limit what you do with
|
||||||
|
your data
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex-1 relative aspect-auto rounded-3xl overflow-hidden shadow-2xl ring-4 ring-gradient-to-r from-orange-200 to-amber-200 hover:scale-105 transition-all duration-500">
|
||||||
|
<Image src="/landing/export.webp" alt="Export" width={1200} height={1081} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -311,8 +336,8 @@ export default function LandingPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="grid md:grid-cols-2 gap-16">
|
<div className="grid md:grid-cols-2 gap-16">
|
||||||
{/* Self-Hosted Version */}
|
{/* Self-Hosted Version */}
|
||||||
<div className="bg-gradient-to-br from-white via-violet-50/50 to-indigo-50/50 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-violet-200 to-indigo-200 hover:shadow-2xl transition-all duration-500 hover:scale-105 group">
|
<div className="bg-gradient-to-br from-white via-violet-50/50 to-indigo-50/50 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-violet-200 to-indigo-200 hover:shadow-2xl transition-all duration-500 group">
|
||||||
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-violet-500 to-indigo-600 text-white text-sm font-bold mb-4 shadow-lg">
|
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-violet-500 to-indigo-600 text-white text-sm font-bold mb-6 shadow-lg">
|
||||||
🏠 Use Your Own Server
|
🏠 Use Your Own Server
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-bold mb-4">
|
<h3 className="text-2xl font-bold mb-4">
|
||||||
@@ -346,8 +371,8 @@ export default function LandingPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Cloud Version */}
|
{/* Cloud Version */}
|
||||||
<div className="bg-gradient-to-br from-white via-pink-50/50 to-purple-50/50 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-pink-200 to-purple-200 hover:shadow-2xl transition-all duration-500 hover:scale-105 group relative">
|
<div className="bg-gradient-to-br from-white via-pink-50/50 to-purple-50/50 p-8 rounded-3xl shadow-xl ring-2 ring-gradient-to-r from-pink-200 to-purple-200 hover:shadow-2xl transition-all duration-500 group relative">
|
||||||
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-pink-500 to-purple-600 text-white text-sm font-bold mb-4 shadow-lg">
|
<div className="inline-block px-4 py-2 rounded-full bg-gradient-to-r from-pink-500 to-purple-600 text-white text-sm font-bold mb-6 shadow-lg">
|
||||||
☁️ We Host It For You
|
☁️ We Host It For You
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-bold mb-4">
|
<h3 className="text-2xl font-bold mb-4">
|
||||||
@@ -356,15 +381,15 @@ export default function LandingPage() {
|
|||||||
<ul className="space-y-3 text-gray-700 mb-8">
|
<ul className="space-y-3 text-gray-700 mb-8">
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-3 text-lg">🎯</span>
|
<span className="text-purple-600 mr-3 text-lg">🎯</span>
|
||||||
SaaS version for those who prefer less hassle
|
SaaS version if you don't want to hassle with own servers
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-3 text-lg">🤖</span>
|
<span className="text-purple-600 mr-3 text-lg">🤖</span>
|
||||||
We provide AI keys and storage
|
We provide you with AI keys and storage
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-3 text-lg">💳</span>
|
<span className="text-purple-600 mr-3 text-lg">💳</span>
|
||||||
Yearly subscription plans
|
Yearly subscription plans. No hidden fees
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<span className="text-purple-600 mr-3 text-lg">🚀</span>
|
<span className="text-purple-600 mr-3 text-lg">🚀</span>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 674 KiB |
|
Before Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 271 KiB |
|
Before Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 657 KiB |
|
Before Width: | Height: | Size: 314 KiB |
@@ -1,3 +1,4 @@
|
|||||||
|
import { generateUUID } from "@/lib/utils"
|
||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
|
|
||||||
interface Progress {
|
interface Progress {
|
||||||
@@ -38,7 +39,7 @@ export function useProgress(options: UseProgressOptions = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const progressId = crypto.randomUUID()
|
const progressId = generateUUID()
|
||||||
const source = new EventSource(`/api/progress/${progressId}?type=${type}`)
|
const source = new EventSource(`/api/progress/${progressId}?type=${type}`)
|
||||||
setEventSource(source)
|
setEventSource(source)
|
||||||
|
|
||||||
|
|||||||
36
lib/utils.ts
@@ -80,3 +80,39 @@ export function encodeFilename(filename: string): string {
|
|||||||
const encoded = encodeURIComponent(filename)
|
const encoded = encodeURIComponent(filename)
|
||||||
return `UTF-8''${encoded}`
|
return `UTF-8''${encoded}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function generateUUID(): string {
|
||||||
|
// Try to use crypto.randomUUID() if available (modern browsers and Node.js 14.17+)
|
||||||
|
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
||||||
|
try {
|
||||||
|
return crypto.randomUUID()
|
||||||
|
} catch (error) {
|
||||||
|
// Fall through to next method
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to crypto.getRandomValues() for UUID v4 generation
|
||||||
|
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
||||||
|
try {
|
||||||
|
const bytes = new Uint8Array(16)
|
||||||
|
crypto.getRandomValues(bytes)
|
||||||
|
|
||||||
|
// Set version (4) and variant bits according to RFC 4122
|
||||||
|
bytes[6] = (bytes[6] & 0x0f) | 0x40 // Version 4
|
||||||
|
bytes[8] = (bytes[8] & 0x3f) | 0x80 // Variant 10
|
||||||
|
|
||||||
|
// Convert to UUID string format
|
||||||
|
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("")
|
||||||
|
return [hex.slice(0, 8), hex.slice(8, 12), hex.slice(12, 16), hex.slice(16, 20), hex.slice(20, 32)].join("-")
|
||||||
|
} catch (error) {
|
||||||
|
// Fall through to Math.random() fallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final fallback using Math.random() (RFC 4122 compliant UUID v4)
|
||||||
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
||||||
|
const r = (Math.random() * 16) | 0
|
||||||
|
const v = c === "x" ? r : (r & 0x3) | 0x8
|
||||||
|
return v.toString(16)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -46,6 +46,16 @@ export const updateCategory = async (userId: string, code: string, category: Cat
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const deleteCategory = async (userId: string, code: string) => {
|
export const deleteCategory = async (userId: string, code: string) => {
|
||||||
|
await prisma.transaction.updateMany({
|
||||||
|
where: {
|
||||||
|
userId,
|
||||||
|
categoryCode: code,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
categoryCode: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
return await prisma.category.delete({
|
return await prisma.category.delete({
|
||||||
where: { userId_code: { userId, code } },
|
where: { userId_code: { userId, code } },
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -46,6 +46,16 @@ export const updateProject = async (userId: string, code: string, project: Proje
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const deleteProject = async (userId: string, code: string) => {
|
export const deleteProject = async (userId: string, code: string) => {
|
||||||
|
await prisma.transaction.updateMany({
|
||||||
|
where: {
|
||||||
|
userId,
|
||||||
|
projectCode: code,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
projectCode: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
return await prisma.project.delete({
|
return await prisma.project.delete({
|
||||||
where: { userId_code: { code, userId } },
|
where: { userId_code: { code, userId } },
|
||||||
})
|
})
|
||||||
|
|||||||
BIN
public/landing/ai-scanner-big.webp
Normal file
|
After Width: | Height: | Size: 240 KiB |
|
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 177 KiB |
BIN
public/landing/invoice-generator.webp
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
public/landing/main-page.webp
Normal file
|
After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 226 KiB |
BIN
public/landing/transactions-big.webp
Normal file
|
After Width: | Height: | Size: 159 KiB |