Skip to content

Repository files navigation

Miku Logo

Miku

A premium AniList client for Android & Desktop built with Wails 3

Wails 3 Vue 3 Go TypeScript License


About

Miku is a feature-rich AniList client that delivers a premium anime and manga tracking experience on Android and Desktop. Built with Wails 3, it combines a Go backend for OAuth2 authentication with a Vue 3 frontend featuring a custom anime-inspired design language with cherry blossom motifs and switchable light/dark/black themes.

Features

Core Features

  • OAuth2 Authentication — Secure login via AniList's OAuth2 flow with localhost callback (works on desktop and Android)
  • Trending & Discovery — Browse trending, popular, seasonal anime, and top manga
  • Advanced Search — Full-text search with anime/manga/character/staff type filters
  • Personal Lists — Manage your anime lists (Watching, Planning, Completed, Dropped, Paused)
  • List Management — Add/update anime to your list directly from detail pages (status, score, progress)
  • Activity Feed — Following-style feed showing your own activity plus the activity of everyone you follow on AniList (like the AniList site). Post status updates with the built-in composer; activity text renders as rich markdown. Tap a friend's avatar to open their AniList profile
  • Profile & Stats — View your profile with detailed statistics and breakdowns (genres, tags, studios, staff, voice actors), favourites (anime, manga, characters, staff), following/followers, paginated activity history, and an activity heatmap

In-App Updates

  • Update Notifications — Bell icon on Discover page checks GitHub Releases for new versions
  • Download APK — Download updates directly in the app with real-time progress (speed, file size)
  • Auto-Install — Opens the system installer after download
  • Version Display — Profile page shows current version with update indicator

Notification Features

  • Update Settings Card — Check the installed version and latest release directly from Settings
  • Episode Notifications — The Discover notification bell alerts you when a new episode is available for anime in your Watching list
  • Individual Read Controls — Mark an individual update or episode notification as read
  • Mark All as Read — Clear all update and episode notifications from the bell at once
  • Persistent Episode Read State — Acknowledged episode releases do not repeatedly notify the user

Search Enhancements

  • Character Search — Search by character name to find anime/manga
  • Staff Search — Search by voice actor/staff name to find their works
  • Multi-Type Filters — Switch between Anime, Manga, Characters, and Staff search

Detail Pages

  • Media Details — Full anime/manga detail pages with banner, cover, scores, genres, description, airing info
  • Characters & Voice Actors — View cast with character images and Japanese voice actors
  • Multiple Voice Actors — Shows all voice actors per character with "(child)" tag for child versions
  • Voice Actor Pages — Click any voice actor to see all their voiced roles across anime (uses correct AniList API)
  • Relations — Navigate between related anime (prequels, sequels, adaptations)
  • Recommendations — Discover similar anime (deduplicated)

Auto-Sync

  • Real-time List Sync — Your anime list auto-syncs with AniList every 60 seconds
  • Activity Refresh — Feed updates automatically when you switch tabs

UI/UX

  • Theme Modes — Dark (default), Light, Black (AMOLED), and System (follows OS) via design-token overrides
  • Accent Color Picker — Preset swatches plus a custom color chooser that re-tints the whole UI
  • Cherry Blossom Motifs — Unique branding with sakura-inspired animations
  • Smooth Animations — Page transitions, skeleton loading, micro-interactions
  • Virtual Scrolling — Optimized list rendering for smooth 60 FPS performance
  • Mobile-First Design — Optimized for Android and desktop
  • Pull-to-Refresh — Touch-based on mobile, manual button on desktop; available on Discover, My List, and Feed. Direction-locked to prevent conflicts with horizontal pill filters

Personalization Settings

  • Title Language — Choose romaji / English / native titles, or follow your AniList account setting
  • Score Format — 100-point, 10-point, 10-point decimal, 5-star, or 3-point display
  • Default Tab — Start the app on Discover, Search, My List, Feed, or Profile
  • Adult Content Toggle — Filter adult titles in browse/search, defaulting to your AniList account setting
  • Recent Activity Toggle — Show or hide the recent activity feed on your profile (off by default)
  • Stats Breakdown Toggles — Individually show or hide Top Genres, Top Tags, Top Studios, Top Staff, and Top Voice Actors sections (all on by default)
  • Collapsible Stats on Mobile — Stats breakdown sections (genres, tags, studios, staff, voice actors) use collapsible dropdown headers on mobile for a cleaner view; desktop keeps them always expanded

Technical

  • GraphQL API — Efficient data fetching with AniList's GraphQL API
  • Type Safety — Full TypeScript coverage with strict mode
  • State Management — Pinia stores for reactive state handling
  • Cross-Platform — Works on Windows, macOS, Linux, and Android
  • Testing — Go suites with testify (unit, integration via httptest, regression, chaos) and Vitest frontend suites; run everything with wails3 task test

Screenshots

Discover Search My List Feed Settings

Tech Stack

Layer Technology Purpose
Desktop/Mobile Framework Wails 3 Cross-platform native apps with Go
Frontend Vue 3 + TypeScript UI rendering and state management
Build Tool Vite Fast development and production builds
State Management Pinia Reactive state stores
Routing Vue Router Client-side navigation
Backend Go 1.25 OAuth2 localhost server, update service, business logic
API AniList GraphQL Anime/manga data (via frontend fetch)
Testing Testify + Vitest Go assertions + frontend unit/integration suites

Prerequisites

  • Go 1.25 or later — install guide
  • Node.js 18+ and npm — install guide
  • Wails 3 CLIgo install github.com/wailsapp/wails/v3/cmd/wails3@latest
  • Android SDK (for Android builds) — install guide

Installation

1. Clone the repository

git clone https://github.com/Aswanidev-vs/Miku.git
cd Miku

2. Install frontend dependencies

cd frontend
npm install
cd ..

3. Set up AniList API credentials

Create a .env file in the project root:

ANILIST_CLIENT_ID=your-client-id
ANILIST_CLIENT_SECRET=your-client-secret

See AniList API Setup below for detailed instructions.

4. Run in development mode

wails3 dev

This starts both the Go backend and the Vite dev server with hot-reload.

5. Build for production

wails3 build

The compiled binary will be placed in the build directory.

Building for Windows

Prerequisites

  • Windows 10 or later
  • Inno Setup 6

Build the Windows executable and installer with:

wails3 task windows:package FORMAT=inno ARCH=amd64

The installer is written to bin/Miku--windows-setup.exe. It opens the normal Inno Setup directory picker and defaults to C:\Program Files\Miku. Users can choose another drive and folder, such as E:\Miku; the selected Miku directory is created automatically and the application is installed there. The installer also handles the Microsoft Edge WebView2 Runtime and creates Start Menu and optional desktop shortcuts.

FORMAT=nsis remains available for the existing NSIS package, and FORMAT=msix creates an MSIX package.

Building for Android

Prerequisites

  • Android SDK (API level 33+)
  • Java Development Kit (JDK 17+)
  • Android NDK

Notes

  • The app includes a network_security_config.xml that allows cleartext HTTP to localhost for the OAuth callback
  • OAuth on Android uses Chrome Custom Tabs redirecting to http://localhost:43219/callback (there is no custom-scheme deep link — Chrome Custom Tabs cannot navigate to custom-scheme URLs)
  • Debug builds keep the x86_64 ABI so the app also runs in the Android Emulator; release/device APKs are arm64-v8a only
  • APK updates downloaded from GitHub use Android's system package installer. On the first update, Android may ask you to allow Miku to install unknown apps; after that setting is enabled, the updater resumes automatically.

Build Size Optimizations

The installed size is dominated by the Go libwails.so native library, so release builds are tuned to minimize it:

  • arm64-v8a only for releasex86_64 is restricted to debug builds. Every real device is arm64, so release APKs stop shipping the redundant x86_64 .so.
  • Stripped symbols by default — Android builds run with PRODUCTION=true, linking Go with -ldflags="-w -s" (no debug info), shrinking libwails.so by roughly 40–50%.
  • R8 shrinking without obfuscation — Release builds enable R8 minification for dead-code removal while keeping -dontobfuscate, so the Go↔Java JNI bridge methods are never renamed. -dontwarn rules cover annotation classes (javax.annotation.*, checkerframework, errorprone) pulled in transitively by androidx.security-crypto (Tink/Guava) that aren't present at runtime, keeping the release build green.

Build Commands

# Generate Wails bindings
wails3 generate bindings

# Build APK
wails3 task android:build

# Build and run on emulator
wails3 task android:run

Output

  • Debug APK: build/android/app/build/outputs/apk/debug/app-debug.apk
  • Release APK: build/android/app/build/outputs/apk/release/app-release.apk (also copied to bin/miku.apk)

Release signing and seamless updates

The Android application ID is intentionally kept as com.wails.app. Android can install a new APK over an existing installation only when the application ID and signing certificate match, and the new versionCode is higher. Release version metadata is read from main.go; for example, 0.12.0 produces a versionCode of 12000.

Never publish a release APK signed with a debug key. Debug keystores are machine-specific, so a new CI runner would make the same package look like a different app. Release builds require these repository secrets:

  • ANDROID_KEYSTORE_BASE64 — base64-encoded copy of the persistent release keystore
  • ANDROID_KEYSTORE_PASSWORD
  • ANDROID_KEY_ALIAS
  • ANDROID_KEY_PASSWORD

Create the keystore once, store it securely, and add its base64 output as a GitHub Actions secret. Do not commit the keystore or its passwords:

keytool -genkeypair -v -keystore miku-release.keystore \
  -alias miku-release -keyalg RSA -keysize 4096 -validity 10000
base64 -w 0 miku-release.keystore

After this setup, published APKs remain installable as updates without users uninstalling the previous version. An APK already installed with an unknown, different signing key cannot be repaired by Java, XML, or the installer intent; Android requires a one-time uninstall unless the original private key can be recovered and used for the next release.

AniList API Setup

Miku uses the AniList GraphQL API with OAuth2 authentication. The app runs a local HTTP server on port 43219 to receive the OAuth callback — this works on both desktop and Android (Chrome Custom Tabs redirect to http://localhost:43219/callback on the device).

Register Your Application

  1. Go to anilist.co/settings/developer
  2. Click "Create New Client"
  3. Fill in the details:
    • Name: Miku (or anything you prefer)
    • Redirect URL: http://localhost:43219/callback
  4. Click "Create"
  5. Copy the generated Client ID and Client Secret

Setting Environment Variables

Windows (PowerShell):

$env:ANILIST_CLIENT_ID = "your-client-id"
$env:ANILIST_CLIENT_SECRET = "your-client-secret"

Windows (Command Prompt):

set ANILIST_CLIENT_ID=your-client-id
set ANILIST_CLIENT_SECRET=your-client-secret

macOS / Linux:

export ANILIST_CLIENT_ID="your-client-id"
export ANILIST_CLIENT_SECRET="your-client-secret"

Persistent (.env file):

Create a .env file in the project root:

ANILIST_CLIENT_ID=your-client-id
ANILIST_CLIENT_SECRET=your-client-secret

Note: Add .env to .gitignore to avoid committing credentials.

Project Structure

Miku/
├── backend/
│   ├── api/
│   │   ├── client.go          # GraphQL client implementation
│   │   ├── queries.go         # AniList query definitions
│   │   └── mutations.go       # AniList mutation definitions
│   ├── auth/
│   │   ├── oauth2.go          # OAuth2 authentication service
│   │   └── token_store.go     # Secure token persistence
│   ├── update/
│   │   ├── update.go          # In-app update service (GitHub Releases)
│   │   └── update_test.go     # Update service tests
│   └── platform/
│       └── platform.go        # OS/arch detection service
├── frontend/
│   ├── src/
│   │   ├── api/
│   │   │   └── graphql.ts     # GraphQL client with cache
│   │   ├── components/
│   │   │   ├── anime/
│   │   │   │   ├── AnimeCard.vue      # Anime card component
│   │   │   │   └── AnimeGrid.vue      # Virtualized grid
│   │   │   ├── layout/
│   │   │   │   ├── BottomNav.vue      # Bottom navigation
│   │   │   │   └── UpdateNotification.vue  # Update bell & panel
│   │   │   ├── profile/
│   │   │   │   ├── HeatmapCalendar.vue   # Activity heatmap
│   │   │   │   ├── StatsCard.vue         # User statistics
│   │   │   │   ├── StatsBreakdown.vue    # Genre/tag/studio/staff/VA breakdowns
│   │   │   │   ├── SocialList.vue        # Following / followers lists
│   │   │   │   └── UserFavorites.vue     # Favorite anime/manga/characters/staff
│   │   │   ├── feed/
│   │   │   │   ├── ActivityComposer.vue  # Post new status updates
│   │   │   │   └── ActivityItem.vue      # Shared activity row (feed + history)
│   │   │   ├── settings/
│   │   │   │   ├── AppearanceSettings.vue  # Theme & accent picker
│   │   │   │   └── AniListPreferences.vue  # AniList account preferences
│   │   │   └── common/
│   │   │       ├── SkeletonLoader.vue # Loading skeleton
│   │   │       └── PullToRefresh.vue  # Pull-to-refresh component
│   │   ├── composables/
│   │   │   ├── usePlatform.ts   # Platform detection
│   │   │   ├── useSettings.ts   # App settings (theme, accent, preferences)
│   │   │   ├── useUpdate.ts     # Update state management
│   │   │   └── usePullToRefresh.ts  # Pull-to-refresh logic
│   │   ├── utils/
│   │   │   ├── activityHtml.ts    # DOMPurify-sanitized activity rendering
│   │   │   ├── activityFormat.ts  # Relative time + status labels
│   │   │   └── mediaDisplay.ts    # Title language + score formatting
│   │   ├── views/
│   │   │   ├── DiscoverView.vue       # Discovery (Trending, Popular, Seasonal, Top Manga)
│   │   │   ├── SearchView.vue         # Search with anime/manga/character/staff filters
│   │   │   ├── MyListView.vue         # Personal lists with status tabs + auto-sync
│   │   │   ├── FeedView.vue           # Activity feed
│   │   │   ├── ProfileView.vue        # User profile with heatmap & version
│   │   │   ├── MediaDetailView.vue    # Anime/manga detail with list management
│   │   │   ├── VoiceActorView.vue     # Voice actor page with voiced roles
│   │   │   ├── CharacterView.vue      # Character detail page
│   │   │   ├── SettingsView.vue       # Redirects to profile settings
│   │   │   └── LoginView.vue          # Login
│   │   ├── stores/
│   │   │   ├── auth.ts                # Authentication state
│   │   │   ├── anime.ts               # Anime data
│   │   │   ├── manga.ts               # Manga data
│   │   │   └── user.ts                # User data
│   │   ├── router/
│   │   │   └── index.ts               # Route definitions
│   │   ├── types/
│   │   │   └── index.ts               # TypeScript types
│   │   ├── styles/
│   │   │   ├── variables.css           # Design tokens
│   │   │   ├── base.css               # Base styles
│   │   │   └── animations.css         # Animations
│   │   ├── App.vue                    # Root component
│   │   └── main.ts                    # Entry point
│   └── public/
│       └── logo.svg                   # App logo
├── build/
│   ├── android/               # Android build config
│   ├── ios/                   # iOS build config
│   ├── darwin/                # macOS build config
│   ├── windows/               # Windows build config
│   └── linux/                 # Linux build config
├── docs/
│   └── compose/               # Specs, plans, reports
├── main.go                    # Application entry point
├── go.mod                     # Go module definition
├── go.sum                     # Go dependencies
└── Taskfile.yml               # Task runner config

Development

Available Scripts

# Development mode with hot-reload
wails3 dev

# Build for production
wails3 build

# Generate Wails bindings
wails3 generate bindings

# Build for Android
wails3 task android:build

# Run on Android emulator
wails3 task android:run

# Run all tests (Go + frontend)
wails3 task test

# Run Go tests only
go test ./... -v

# Run frontend tests only
cd frontend && npm test

# Frontend only (without Go backend)
cd frontend && npm run dev

Code Style

  • Vue: Composition API with <script setup lang="ts">
  • TypeScript: Strict mode enabled
  • CSS: Custom properties (CSS variables) for theming
  • Go: Standard Go formatting with gofmt

Git Conventions

Follow Conventional Commits:

feat:     New feature
fix:      Bug fix
docs:     Documentation changes
style:    Code style changes (formatting, etc.)
refactor: Code refactoring
test:     Adding or updating tests
chore:    Maintenance tasks

CI/CD

This project uses GitHub Actions for automated builds. See .github/workflows/build.yml for the workflow configuration.

Automated Builds

  • Push to main: Creates a version tag; the tag build publishes the Android APK and Windows Inno Setup installer together
  • Version tags: Build both Android and Windows release artifacts and attach them to the GitHub release
  • Pull Request: Validates build compiles successfully
  • Manual trigger: Build from Actions tab

Changelog

Unreleased

New Features

  • Themes — Dark, Light, Black (AMOLED), and System modes plus a custom accent color picker
  • Activity Composer — Post status updates directly from the Feed; activity text now renders as rich markdown
  • Profile Overhaul — Stats breakdowns (genres, tags, studios, staff, voice actors), character/staff favorites, Following/Followers section, About Me, and browsable activity history
  • AniList Preferences — Title language, score format, default tab, and adult content settings (with account-default fallbacks)
  • Feed Pull-to-Refresh — Feed tab now supports the mobile gesture + desktop refresh button
  • Collapsible Stats on Mobile — Stats breakdown sections collapse/expand via dropdown headers with animated chevrons on mobile; desktop keeps them permanently expanded
  • Recent Activity Toggle — New toggle in Preferences (default off) to show or hide the recent activity feed on profile; activity data is only fetched when enabled
  • Stats Visibility Toggles — Individual toggles in Preferences for Top Genres, Top Tags, Top Studios, Top Staff, and Top Voice Actors (all on by default); disabling a toggle hides the corresponding section from the stats breakdown

Bug Fixes

  • Pull-to-Refresh on My List — Fixed dual pull-to-refresh zones and scroll-gets-stuck bug caused by incorrect scroll container detection and missing gesture direction locking; horizontal swipes on filter pills and downward scrolling no longer accidentally trigger refresh

Testing

  • Go — testify suites for the GraphQL client (integration + chaos), OAuth2 flow, token store, and platform service
  • Frontend — Vitest suites (composables, components, utils, Pinia stores); run everything with wails3 task test

v0.9.4

New Features

  • Staff Search — Search by voice actor/staff name to find their works
  • Multiple Voice Actors — Shows all voice actors per character with "(child)" tag for child versions

Bug Fixes

  • Fixed voice actor page not showing all voiced roles (uses correct AniList API)
  • Fixed character images not loading for child voice actors
  • Fixed child VA row not showing character name

v0.9.0

New Features

  • In-App Update Notifications — Bell icon on Discover page checks GitHub Releases for new versions
  • Download APK Updates — Download updates directly in the app with real-time progress (speed, file size)
  • Character Search — Search by character name to find anime/manga
  • Version Display — Profile page shows current version with update indicator
  • Go Tests — Backend tests with testify library

Improvements

  • Activity Heatmap — Now fetches full year of activity data
  • Search UI — Added 4 filter tabs: Anime, Manga, Characters, Staff
  • Mobile Responsive — Update notification bell visible on all devices

Bug Fixes

  • Fixed version not displaying in ProfileView

Notification Behavior

  • The Discover notification bell continues to check automatically for new app releases and shows a badge when an update is available.
  • The Settings menu contains the manual Check for Updates card, which reports whether the installed version is current or an update is available.
  • Anime in the user's Watching list generate a bell notification when AniList reports a newly released episode beyond the user's watched progress.
  • Episode and update notifications support both individual Mark as read actions and Mark all as read.

v0.8.14

  • Initial release with core features

Contributing

Contributions are welcome! Here's how to get started:

  1. Fork the repository
  2. Create a feature branch from main
    git checkout -b feature/your-feature-name
  3. Make your changes
  4. Test your changes in development mode
    wails3 dev
  5. Run the test suites
    wails3 task test
  6. Commit with a descriptive message
    git commit -m "feat: add your feature description"
  7. Push to your fork and open a Pull Request

Development Setup

  1. Follow the Installation steps
  2. Create a .env file with your AniList credentials
  3. Run wails3 dev to start development
  4. Make your changes with hot-reload
  5. Test thoroughly before submitting

License

Android Link Behavior

  • OAuth login links still open in Chrome Custom Tabs on Android because the localhost callback flow depends on that behavior.
  • Staff and voice actor external links use Android's normal app-link resolution instead. If the user has YouTube, Instagram, X/Twitter, or another matching app installed, Android can open that app directly.
  • If no installed app can handle the link, Android falls back to the user's default browser.

This project is licensed under the MIT License. See the LICENSE file for details.

Acknowledgments

  • AniList — For the API and platform
  • Wails — For the cross-platform framework
  • Vue.js — For the frontend framework
  • Pinia — For state management
  • Dexie.js — For IndexedDB wrapper
  • Testify — For Go testing assertions

Made with by Aswanidev-vs

About

Miku is a feature-rich, native Android application for tracking anime and manga on AniList. Built with Wails 3, it combines a high-performance Go backend with a Vue 3 frontend to deliver a smooth experience.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages