আপনি যদি একজন ওয়েব ডেভেলপার হন যিনি অ্যাপ ডেভেলপমেন্ট সম্পর্কে না জানেন (আমার মতো!), তবে এই আর্টিকেলটি আপনার জন্য। আমি আপনাকে শিখাব কীভাবে আপনার ওয়েবসাইটকে একটি নেটিভ অ্যাপে রূপান্তর করবেন, নতুন ফ্রেমওয়ার্ক বা ভাষা ছাড়া। আপনি শিখবেন কীভাবে একটি ওয়েবসাইটকে PWA (Progressive Web App) তে রূপান্তর করবেন যা আপনি প্লে স্টোরে প্রকাশ করতে পারবেন।
প্রথমে, আমরা আপনার ওয়েবসাইটকে একটি Progressive Web App (PWA)-তে রূপান্তর করব। তারপর আমরা Google-এর একটি ফ্রি কমান্ড-লাইন টুল Bubblewrap ব্যবহার করে সেই PWA-কে একটি Android অ্যাপে প্যাকেজ করব। চলুন শুরু করি।
পূর্বশর্ত
এই টিউটোরিয়াল অনুসরণ করতে চাইলে কিছু পূর্বশর্ত রয়েছে:
ওয়েব ডেভেলপমেন্টের βασিক জ্ঞান
আপনার সাইট পাবলিকলি লাইভ থাকতে হবে, এবং আপনাকে এর সোর্স কোডে অ্যাক্সেস থাকতে হবে।
আমরা npm ব্যবহার করব প্রয়োজনীয় টুল ইনস্টল করার জন্য, তাই নিশ্চিত করুন Node.js ইনস্টল করা আছে।
নোট: এই টিউটোরিয়াল একটি Vite প্রজেক্টের উপর ভিত্তি করে, কিন্তু Bubblewrap-এর সাথে ফাইনাল স্টেপগুলো যেকোনো ওয়েব ফ্রেমওয়ার্কের জন্য একই।
সুচিপত্র
PWA কী?
Bubblewrap কী?
TWA (Trusted Web Activity) কী?
TWA কীভাবে আস্থা যাচাই করে
স্টেপ ১ - Vite-এ আপনার PWA কনফিগার করুন
আপনার অ্যাপ আইকন তৈরি করুন
Vite PWA প্লাগইন ইনস্টল করুন।
প্লাগইন কনফিগার করুন
স্টেপ ২ - Android অ্যাপ তৈরি করুন
একটি বিল্ড ফোল্ডার তৈরি করুন
Bubblewrap CLI ইনস্টল করুন
প্রজেক্ট ইনিশিয়ালাইজ করুন
init কমান্ডের সমস্যা সমাধান করুন।
স্টেপ ৩ - Bubblewrap-এর প্রশ্নের উত্তর দিন
স্টেপ ৪ - অ্যাপ বিল্ড করুন
স্টেপ ৫ - TWA যাচাইকরণ সেটআপ করুন
.well-known ফোল্ডার কী?
delegate_permission/common.handle_all_urls কী?
স্টেপ ৬ (ঐচ্ছিক) - ইন-অ্যাপ অভিজ্ঞতা কাস্টমাইজ করুন
শেষ করুন
PWA কী?
PWA অর্থ Progressive Web Application, এবং এর লক্ষ্য আপনার ওয়েবসাইটকে নেটিভ অ্যাপের মতো লুক এবং ফিল দিতে। আপনি যদি ব্রাউজারে কোনো ওয়েবসাইট ভিজিট করে একটি ইনস্টল আইকন দেখেন যা আপনাকে ফোন বা ল্যাপটপে ডাউনলোড করতে দেয়, তবে আপনি একটি PWA ব্যবহার করেছেন।
কিন্তু এটা শুধু লুক এবং ফিলের বিষয় নয়। একটি PWA-র অ্যাপ-সদৃশ ফিচারও থাকে, যেমন অফলাইন কাজ করা, পশ নোটিফিকেশন পাঠানো, এবং আরও অনেক কিছু।
একটি PWA-এর দুটি মূল কম্পোনেন্ট রয়েছে।
ম্যানিফেস্ট ফাইল আপনার অ্যাপকে বর্ণনা করে, যেমন এর নাম, আইকন, স্টার্ট URL, ইত্যাদি।
একটি সার্ভিস ওয়ার্কার একটি ব্যাকগ্রাউন্ড JavaScript ফাইল যা একটি প্রক্রিয়ার 역할을 করে। ক্যাশিং এবং পশ নোটিফিকেশন একটি সার্ভিস ফাইল দ্বারা হ্যান্ডেল হয়, যা মেইন থ্রেড থেকে আলাদা একটি থ্রেডে চলে।
এই দুটি কম্পোনেন্ট ছাড়া, ব্রাউজাররা ব্যবহারকারীদের অ্যাপটি লোকালি ডাউনলোড করতে দেবে না।
ম্যানিফেস্ট ফাইল এবং সার্ভিস ওয়ার্কার ব্রাউজারের জন্য একটি চেকলিস্টের মতো। আপনি যখন কোনো ওয়েবসাইট ভিজিট করেন, ব্রাউজার এই দুটি কম্পোনেন্ট খোঁজে। যদি সেগুলো উপস্থিত থাকে এবং সঠিকভাবে কনফিগার করা থাকে, ব্রাউজার বুঝতে পারে এটি একটি সত্যিকারের PWA এবং "ইনস্টল" আইকনটি দেখাবে, যা ব্যবহারকারীদের অ্যাপটি লোকালি ডাউনলোড করতে দেবে। এগুলো ছাড়া, ব্রাউজার শুধু একটি সাধারণ ওয়েবসাইট দেখে, এবং ইনস্টল করার অপশনটি উপলব্ধ থাকবে না।
Bubblewrap কী?
Bubblewrap হলো Google তৈরি একটি কমান্ড-লাইন টুল যা আপনার PWA-কে নেয় এবং একটি Trusted Web Activity (TWA) ব্যবহার করে Android অ্যাপে পরিণত করে।
Bubblewrap একটি PWA-এর ম্যানিফেস্ট ফাইল থেকে একটি Android অ্যাপ প্যাকেজ (APK বা AAB) তৈরি করার প্রক্রিয়াকে সহজ করে তোলে।
TWA (Trusted Web Activity) কী?
একটি Trusted Web Activity (TWA) হলো একটি আধুনিক Android ফিচার যা আপনাকে আপনার লাইভ ওয়েবসাইটকে ফুল-স্ক্রিনে একটি Android অ্যাপের ভিতরে দেখাতে দেয়। মূলত, এটি ওয়েবসাইটটি ব্রাউজারে চালায়, কিন্তু অ্যাপে ব্রাউজারের অ্যাড্রেস বার দেখায় না। এটি নেটিভ অ্যাপের অনুভূতি দেয়।
এই ফুল-স্ক্রিন ফিচার আনলক করার জন্য, আপনার অ্যাপকে "Trusted" হতে হবে।
এখানেই "গোপন হ্যান্ডশেক" আসে। Android-কে নিশ্চিত হতে হবে যে অ্যাপ বানানোর ব্যক্তি এবং ওয়েবসাইটের মালিক একই ব্যক্তি। এই মালিকানা প্রমাণ ছাড়া, TWA ফলব্যাক মোডে চলবে এবং উপরে ব্রাউজারের অ্যাড্রেস বার দেখাবে, নেটিভ অ্যাপের অনুভূতি বIgाड़ দেবে।
TWA কীভাবে আস্থা যাচাই করে
এই আস্থা যাচাই করা হয় Digital Asset Links নামক একটি সিস্টেম দিয়ে। আপনি আপনার ওয়েবসাইটে একটি বিশেষ ফাইল রাখবেন (ইমপ্লিমেন্টেশন অংশে করব) যা আপনার অ্যাপের অনন্য ডিজিটাল ফিংগারপ্রিন্ট ধারণ করবে। যখন একজন ব্যবহারকারী আপনার অ্যাপ খুলবে, Android OS এই ফাইলটি চেক করবে। যদি ফিংগারপ্রিন্টগুলো মেলে, তবে এটি আপনার অ্যাপকে "trusted" স্ট্যাটস দেবে, অ্যাড্রেস বার সরিয়ে দেবে, এবং ডিপ লিঙ্কিং সহ অন্যান্য ফিচার সক্ষম করবে।
আপনি এই সম্পর্কটি নিজে যাচাই করতে পারেন Google-এর অফিসিয়াল টেস্টিং টুল দিয়ে: Digital Asset Links Verifier।
এখন আপনি প্রজেক্ট এবং টুলগুলো বুঝতে পেরেছেন, চলুন বিল্ড করা শুরু করি।
স্টেপ ১ - Vite-এ আপনার PWA কনফিগার করুন
প্রথম ধাপ হলো PWA-এর দুটি মূল কম্পোনেন্ট যোগ করা: ম্যানিফেস্ট ফাইল এবং সার্ভিস ওয়ার্কার। এগুলো ব্রাউজারকে এটি "ইনস্টলযোগ্য" হিসাবে চিনতে দেবে।
এই গাইডটি Vite-তে বিল্ড করা একটি প্রজেক্টের উপর ভিত্তি করে, যা একটি স্পেশাল প্লাগইন দিয়ে এই প্রক্রিয়াকে সহজ করে দেয়। আপনি যদি অন্য টুল ব্যবহার করেন, তবে কনসেপ্টগুলো একই, কিন্তু আপনাকে আপনার এনভায়রনমেন্টের জন্য নির্দিষ্ট স্টেপগুলোর জন্য আলাদা রিসোর্স খুঁজে বের করতে হবে।
আপনার অ্যাপ আইকন তৈরি করুন
কোনো কোড ছুঁয়ে দেওয়ার আগে, আমাদের অ্যাপের জন্য আইকন দরকার। Android অ্যাপের লঞ্চার আইকন (যেটি হোম স্ক্রিনে দেখেন) এবং স্প্ল্যাশ স্ক্রিন (অ্যাপ শুরু হলে যা দেখেন) এর জন্য নির্দিষ্ট সাইজ চায়।
আপনার দুটি মূল সাইজ লাগবে: 192x192 পিক্সেল এবং 512x512 পিক্সেল। আপনি এই Favicon Generator ব্যবহার করে আপনার লোগোকে নির্দিষ্ট সাইজে জেনারেট করতে পারেন। আপনার মেইন লোগো আপলোড করুন, এবং এটি আপনার জন্য সব প্রয়োজনীয় সাইজ জেনারেট করবে।
তারপর জেনারেট করা ফাইলগুলো ডাউনলোড করুন এবং 192x192 এবং 512x512 ফাইলগুলো আপনার প্রজেক্টের public ফোল্ডারে রাখুন।

Vite PWA প্লাগইন ইনস্টল করুন।
একটি PWA-র জন্য ম্যানিফেস্ট ফাইল এবং একটি সার্ভিস ওয়ার্কার দরকার। আমরা এগুলো ম্যানুয়ালি তৈরি করতে পারি, কিন্তু এই প্লাগইন সার প্রক্রিয়াটি অটোমেট করে দেয়। এটি প্রতিবার আপনি প্রজেক্ট বিল্ড করলে স্বয়ংক্রিয়ভাবে manifest.json এবং service-worker.js জেনারেট করবে।
npm install vite-plugin-pwa -D
প্লাগইন কনফিগার করুন
এই ধাপে, আমরা এই প্লাগইন ব্যবহার করে আমাদের অ্যাপের ম্যানিফেস্ট কনফিগার করব। vite.config.ts ফাইলটি এডিট করুন। এই কনফিগারেশন প্লাগইনকে বলবে আপনার অ্যাপকে কী নাম দেবে, কোন আইকনগুলো ব্যবহার করবে, ইত্যাদি।
vite.config.ts-এ:
export default defineConfig({ plugins: [ VitePWA({ registerType: "autoUpdate", manifest: { name: "your app name", short_name: "your app short name", description: "write any description", theme_color: "#0d1117", background_color: "#ffffff", display: "standalone", start_url: "/", icons: [ { src: "/web-app-manifest-192x192.png", sizes: "192x192", type: "image/png", }, { src: "/web-app-manifest-512x512.png", sizes: "512x512", type: "image/png", }, ], }, }), ]
এখন, আপনি npm run build চালালে, প্লাগইন স্বয়ংক্রিয়ভাবে ম্যানিফেস্ট এবং সার্ভিস ওয়ার্কার ফাইলগুলো জেনারেট করবে। তারপর পরিবর্তনগুলো ডিপ্লয় করুন। এখন আপনার ওয়েবসাইট একটি PWA।
স্টেপ ২ - Android অ্যাপ তৈরি করুন
এখন আপনার ওয়েবসাইট একটি PWA, চলুন Bubblewrap ব্যবহার করে এটিকে একটি Android অ্যাপে প্যাকেজ করি।
একটি বিল্ড ফোল্ডার তৈরি করুন
আপনার Android প্রজেক্ট ফাইলগুলোর জন্য একটি ডেডিকেটেড ফোল্ডার তৈরি করুন। আপনার প্রজেক্টের রুটে একটি নতুন ফোল্ডার তৈরি করুন। আমি আমারটিকে android নাম দিচ্ছি।
project/ ├── client/ ├── server/ └── android/
এখন আপনার তৈরি করা নতুন ফোল্ডারে নেভিগেট করুন।
Bubblewrap CLI ইনস্টল করুন
npm install -g @bubblewrap/cli
প্রজেক্ট ইনিশিয়ালাইজ করুন
এরপর init কমান্ড চালান। Bubblewrap আপনার লাইভ ওয়েবসাইটের সাথে সংযুক্ত হবে, Vite তৈরি করা manifest.webmanifest ফাইলটি পড়বে, এবং সেই ইনফরমেশন ব্যবহার করে একটি বেসিক Android প্রজেক্ট জেনারেট করবে।
bubblewrap init --manifest=https://your-website-domain/manifest.webmanifest
কমান্ডটি চালান, your-website-domain-কে আপনার আসল URL দিয়ে প্রতিস্থাপন করে:
init কমান্ডের সমস্যা সমাধান করুন
init কমান্ড চালানোর সাথে সাথে, Bubblewrap দুটি কী সফটওয়্যার প্যাকেজ চাইবে: Java Development Kit (JDK) এবং Android SDK। এটি সেগুলো ইনস্টল করার অফার দেবে।
JDK সেটআপ:
? Do you want Bubblewrap to install the JDK (recommended)? (Enter "No" to use your own JDK 17 installation) (Y/n)
আমার কেসে, যখন আমি Bubblewrap-কে JDK ইনস্টল করতে দিলাম, প্রক্রিয়াটি ফাইলগুলো ডাউনলোড করল কিন্তু "decompressing" ধাপে ফেল করে গেল। আপনি যদি একই সমস্যায় পড়েন, চিন্তা করবেন না! সমাধান হলো ম্যানুয়ালি ইনস্টল করা।
প্রম্পটে No বলুন।
সুপারিশকৃত ভার্সন (সাধারণত JDK 17) Adoptium-এর মতো সোর্স থেকে ডাউনলোড করুন।
ইনস্টল করুন এবং আপনার সিস্টেমের এনভায়রনমেন্ট ভেরিয়েবল সেট আপ করুন JDK-এর
binপাথ সহ। আপনি যদি না জানেন এনভায়রনমেন্ট ভেরিয়েবল কীভাবে সেট করতে হয়, তবে এই সাইটটি চেক করতে পারেন: Set Environment Variables।যখন Bubblewrap পাথ চাইবে, সরাসরি দিন, যেমন
C:\java\jdk-17.0.16.8-hotspot।
Android SDK সেটআপ:
JDK সফলভাবে সেট আপ হলে, পরবর্তী ধাপ হলো Android SDK কনফিগার করা।
? Do you want Bubblewrap to install the Android SDK (recommended)? (Enter "No" to use your own Android SDK installation) (Y/n)
যেহেতু আমার Android SDK ছিল না, আমি Bubblewrap-কে Yes সিলেক্ট করে হ্যান্ডেল করতে দিলাম। আমি এখানে কোনো সমস্যায় পড়িনি।
আপনি যদি Android SDK সেটআপে কোনো সমস্যায় পড়েন, তবে সেটি ম্যানুয়ালি সেট আপ করুন এবং পাথ দিন, JDK সেটআপের মতো।
স্টেপ ৩ - Bubblewrap-এর প্রশ্নের উত্তর দিন
SDK সেট আপ হলে, Bubblewrap আপনার অ্যাপ কনফিগার করার জন্য একগাদা প্রশ্ন করবে। এই ইনফরমেশনটি twa-manifest.json ফাইল তৈরি করতে ব্যবহৃত হবে, যা আপনার অ্যাপের ব্লুপ্রিন্ট।
Domain: Enter চাপুন (আপনার ম্যানিফেস্ট থেকে অটো-ফিল্ড) Application name: আপনার পূর্ণ অ্যাপ নাম Application ID: (যেমন, chat.yourapp.twa) Display mode: standalone Orientation: portrait Status bar color: Enter চাপুন (ডিফল্ট গ্রহণ করে) Splash screen color: Enter চাপুন (ডিফল্ট গ্রহণ করে) Icon URL: Enter চাপুন (ডিফল্ট গ্রহণ করে) Include support for Play Billing?: আপনার অ্যাপ Google Play ইন-অ্যাপ পরচেজ ব্যবহার করলে Y, অন্যথায় N Request geolocation permission?: আপনার অ্যাপ লোকেশন অ্যাক্সেস প্রয়োজন হলে Y, অন্যথায় N
এই প্রশ্নগুলোর মধ্যে গুরুত্বপূর্ণ অংশ হলো কীস্টোর এবং কী।
First and Last names: আপনার পূর্ণ নাম Organizational Unit: Developer বা যেকোনো কিছু Organization: আপনার প্রতিষ্ঠানের নাম Country (2-letter code): আপনার কান্ট্রি কোড Password for key store: একটি নতুন পাসওয়ার্ড দিন Password for key: একই পাসওয়ার্ড পুনরায় দিন
নোট: কীস্টোর এবং কী উভয়ের পাসওয়ার্ড একই হতে হবে, অন্যথায় এরর থ্রো করবে। এই ইস্যুটি দেখুন: Bubblewrap Issue।
স্টেপ ৪ - অ্যাপ বিল্ড করুন
bubblewrap build --universalApk
এই কমান্ড আপনার অ্যাপ্লিকেশন বিল্ড করা শুরু করবে। এখানে universalApk ফ্ল্যাগ .apk এবং .abb উভয় ফাইল তৈরি করবে। আপনি যদি প্লে স্টোরে প্রকাশ করতে চান, তবে .abb ফাইল আপলোড করুন। আমাদের টেস্টের জন্য APK ফাইল লাগবে, তাই এই ফ্ল্যাগ universalApk দুটি ফাইলই তৈরি করবে। যদি আমরা এই ফ্ল্যাগ দিই না, তবে শুধু .abb ফাইল পাব।
স্টেপ ৫ - TWA যাচাইকরণ সেটআপ করুন
বিল্ড হলে, আপনাকে APK পাওয়া যাবে। এটিকে আপনার ফোনে ট্রান্সফার করুন এবং টেস্ট করুন। আপনি যখন অ্যাপ খুলবেন, ব্রাউজারের অ্যাড্রেস বার দেখবেন। এর কারণ হলো আমরা এখনো আপনার অ্যাপ এবং ওয়েবসাইটের মাঝপথে "আস্থা" সেট আপ করিনি। চলুন এখন সেটি ঠিক করি।
আপনার ফ্রন্টএন্ড প্রজেক্টে, public ফোল্ডারে যান, একটি নতুন ফোল্ডার তৈরি করুন .well-known নামে, এবং তার ভেতরে একটি ফাইল তৈরি করুন assetlinks.json নামে।
frontend/ ├── public/ ├── .well-known/ └── assetlinks.json
.well-known ফোল্ডার কী?
A well-known folder is used to store files that define configurations for protocols, as it’s used for external sources to find the validation for your website. In our case, our app checks the well-known folder from our website and verifies the validation.
assetlinks.json-এ নিচের কন্টেন্ট পেস্ট করুন:
[ { "relation": ["delegate_permission/common.handle_all_urls"], "target": { "namespace": "android_app", "package_name": "chat.yourapp.twa", "sha256_cert_fingerprints": [ "your_sha256_fingerprint" ] } } ]
delegate_permission/common.handle_all_urls কী?
এটি একটি 스페সিয়াল ফ্ল্যাগ যা ডোমেনের বদলে অ্যাপ থেকে সব লিংক খুলে। সহজ কথায়, এটি একটি ডিপ লিঙ্ক হিসেবে কাজ করে। আপনি অ্যাপ ইনস্টল করার পর, আপনার ওয়েবসাইটের লিংক যদি WhatsApp বা কোথাও থেকে ক্লিক করেন, তবে এটি ব্রাউজারে খুলবেনা, বরং আপনার অ্যাপে খুলবে, ডিপ লিঙ্ক হিসেবে কাজ করবে।
package_name ফিল্ডটি হবে packageId, যা আপনি আপনার Android বিল্ড ফোল্ডারের twa-manifest.json- থেকে পেতে পারেন।
এখন আপনার ফিংগারপ্রিন্ট পান। নিচের কমান্ড চালান:
keytool -list -v -keystore android.keystore -alias android
অ্যালিয়াস নামটি হবে যা আপনি তৈরি করেছেন। এই কমান্ড চালালে, এটি কীস্টোর পাসওয়ার্ড চাইবে। সেটি দিলে আপনি আপনার SHA256 ফিংগারপ্রিন্ট পাবেন। সেটি কপি করে assetslinks.json ফাইলের sha256_cert_fingerprints অ্যারেতে পেস্ট করুন। এখন এই পরিবর্তনগুলো প্রোডাকশনে পুশ করুন। আপনি Digital Asset Links-এ যাচাইকরণ যাচাই করতে পারেন।
বস! এখন আপনি অ্যাপটি ইনস্টল করে টেস্ট করতে পারেন।
স্টেপ ৬ (ঐচ্ছিক) - ইন-অ্যাপ অভিজ্ঞতা কাস্টমাইজ করুন
এখন, এডিশনালি, কিছু কেসে আমরা চাইব ওয়েবসাইটে এবং মোবাইল অ্যাপে ব্যবহারকারীদের ভিন্ন কন্টেন্ট দেখানো। কি আমরা সেটি করতে পারি? হ্যাঁ!
আপনার Android বিল্ড ফোল্ডারে, twa-manifest.json-এ, startUrl নামে একটি ফিল্ড থাকবে। না থাকলে, যোগ করুন এবং ভ্যালু দিন "startUrl": "/?twa=true"। startUrl হলো এন্ট্রি পয়েন্ট। আমি কোয়েরি প্যারামিটার হিসেবে twa=true ব্যবহার করেছি।
আবার bubblewrap build --universalApk দিয়ে বিল্ড চালান।
এখন, আপনি যদি অ্যাপ খুলেন, এটি yourwebsitedomain.com/?twa=true এন্ট্রি URL-এ খুলবে।
আপনার ফ্রন্টএন্ডে:
const twaParam = queryParams.get("twa"); const [isTwa, setIsTwa] = useState<boolean>(() => { return localStorage.getItem("isTwa") === "true"; }); useEffect(() => { if (twaParam === "true") { localStorage.setItem("isTwa", "true"); // set the value to local storage setIsTwa(true); } }, [twaParam]);
{isTwa? ( <Link to="/contact" className="underline hover:text-primary"> Contact </Link> ) : ( <Link to="/download" className="underline hover:text-primary"> Download App </Link> )}
উপরের কোডে, আমরা URL-এ twa=true কোয়েরি প্যারামিটার চেক করেছি। যদি থাকে, তবে আমরা সেটি লোকাল স্টোরেজে সেভ করি, এবং তারপর ব্যবহারকারীর জন্য কন্ডিশনালি কন্টেন্ট রেন্ডার করি।
এটুশ। আমরা একটি অ্যাপ তৈরি করেছি।
আপনি যদি কোনো নাম, রঙ, বা স্প্ল্যাশ স্ক্রিন পরিবর্তন করতে চান, তবে twa-manifest.json-এ পরিবর্তন করে আবার বিল্ড চালাতে পারেন।
শেষ করুন
Bubblewrap শুধু Android-এর জন্য। আপনি যদি ক্রস-প্ল্যাটফর্ম সাপোর্ট চান, তবে কিছু অন্যান্য প্ল্যাটফর্ম আছে, যেমন Capacitor, যা আমি অন্য একটি আর্টিকেলে লিখব।
বolbar, আপনি আমার Bubblewrap দিয়ে বানানো অ্যাপটি দেখতে পারেন এখানে: Stranger Talk।
যদি কোনো ভুল থাকে বা প্রশ্ন থাকে, LinkedIn বা Instagram-এ আমার সাথে যোগাযোগ করুন।
পড়ার জন্য ধন্যবাদ!
Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started